forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#104411 - lcnr:bivariance-nll, r=compiler-er…
…rors nll: correctly deal with bivariance fixes rust-lang#104409 when in a bivariant context, relating stuff should always trivially succeed. Also changes the mir validator to correctly deal with higher ranked regions. r? types cc `@RalfJung`
- Loading branch information
Showing
10 changed files
with
130 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
//! Routines to check for relations between fully inferred types. | ||
//! | ||
//! FIXME: Move this to a more general place. The utility of this extends to | ||
//! other areas of the compiler as well. | ||
|
||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; | ||
use rustc_infer::traits::ObligationCause; | ||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; | ||
use rustc_trait_selection::traits::ObligationCtxt; | ||
|
||
/// Returns whether the two types are equal up to subtyping. | ||
/// | ||
/// This is used in case we don't know the expected subtyping direction | ||
/// and still want to check whether anything is broken. | ||
pub fn is_equal_up_to_subtyping<'tcx>( | ||
tcx: TyCtxt<'tcx>, | ||
param_env: ParamEnv<'tcx>, | ||
src: Ty<'tcx>, | ||
dest: Ty<'tcx>, | ||
) -> bool { | ||
// Fast path. | ||
if src == dest { | ||
return true; | ||
} | ||
|
||
// Check for subtyping in either direction. | ||
is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src) | ||
} | ||
|
||
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. | ||
/// | ||
/// This mostly ignores opaque types as it can be used in constraining contexts | ||
/// while still computing the final underlying type. | ||
pub fn is_subtype<'tcx>( | ||
tcx: TyCtxt<'tcx>, | ||
param_env: ParamEnv<'tcx>, | ||
src: Ty<'tcx>, | ||
dest: Ty<'tcx>, | ||
) -> bool { | ||
if src == dest { | ||
return true; | ||
} | ||
|
||
let mut builder = | ||
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble); | ||
let infcx = builder.build(); | ||
let ocx = ObligationCtxt::new(&infcx); | ||
let cause = ObligationCause::dummy(); | ||
let src = ocx.normalize(cause.clone(), param_env, src); | ||
let dest = ocx.normalize(cause.clone(), param_env, dest); | ||
match ocx.sub(&cause, param_env, src, dest) { | ||
Ok(()) => {} | ||
Err(_) => return false, | ||
}; | ||
let errors = ocx.select_all_or_error(); | ||
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing` | ||
// we would get unification errors because we're unable to look into opaque types, | ||
// even if they're constrained in our current function. | ||
// | ||
// It seems very unlikely that this hides any bugs. | ||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); | ||
errors.is_empty() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// check-pass | ||
// compile-flags: -Zvalidate-mir | ||
|
||
// This test checks that bivariant parameters are handled correctly | ||
// in the mir. | ||
#![allow(coherence_leak_check)] | ||
trait Trait { | ||
type Assoc; | ||
} | ||
|
||
struct Foo<T, U>(T) | ||
where | ||
T: Trait<Assoc = U>; | ||
|
||
impl Trait for for<'a> fn(&'a ()) { | ||
type Assoc = u32; | ||
} | ||
impl Trait for fn(&'static ()) { | ||
type Assoc = String; | ||
} | ||
|
||
fn foo(x: Foo<for<'a> fn(&'a ()), u32>) -> Foo<fn(&'static ()), String> { | ||
x | ||
} | ||
|
||
fn main() {} |