From: matthewjasper Date: Tue, 16 Jun 2020 17:27:40 +0000 (+0100) Subject: Unify region variables when projecting associated types X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=ba2ef58ae6c126ec0b87b307d45fef2da127be22;p=rust.git Unify region variables when projecting associated types This is required to avoid cycles when evaluating auto trait predicates. --- diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index c2dae6ba4f8..8695b9616ee 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -314,18 +314,25 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { } ty::ReVar(vid) => { - let r = self + let resolved_vid = self .infcx .unwrap() .inner .borrow_mut() .unwrap_region_constraints() - .opportunistic_resolve_var(self.tcx, vid); + .opportunistic_resolve_var(vid); debug!( "canonical: region var found with vid {:?}, \ opportunistically resolved to {:?}", vid, r ); + // micro-optimize -- avoid an interner look-up if the vid + // hasn't changed. + let r = if vid == resolved_vid { + r + } else { + self.tcx.mk_region(ty::ReVar(resolved_vid)) + }; self.canonicalize_region_mode.canonicalize_free_region(self, r) } diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 626774617a6..90d61a78f9b 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -50,10 +50,10 @@ pub struct RegionConstraintStorage<'tcx> { /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this /// table. You can then call `opportunistic_resolve_var` early /// which will map R1 and R2 to some common region (i.e., either - /// R1 or R2). This is important when dropck and other such code - /// is iterating to a fixed point, because otherwise we sometimes - /// would wind up with a fresh stream of region variables that - /// have been equated but appear distinct. + /// R1 or R2). This is important when fulfillment, dropck and other such + /// code is iterating to a fixed point, because otherwise we sometimes + /// would wind up with a fresh stream of region variables that have been + /// equated but appear distinct. pub(super) unification_table: ut::UnificationTableStorage, /// a flag set to true when we perform any unifications; this is used @@ -714,13 +714,8 @@ pub fn glb_regions( } } - pub fn opportunistic_resolve_var( - &mut self, - tcx: TyCtxt<'tcx>, - rid: RegionVid, - ) -> ty::Region<'tcx> { - let vid = self.unification_table().probe_value(rid).min_vid; - tcx.mk_region(ty::ReVar(vid)) + pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid { + self.unification_table().probe_value(rid).min_vid } fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index e28cf49c7f2..bda38301f1c 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -46,51 +46,56 @@ fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { } } -/// The opportunistic type and region resolver is similar to the -/// opportunistic type resolver, but also opportunistically resolves -/// regions. It is useful for canonicalization. -pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx> { +/// The opportunistic region resolver opportunistically resolves regions +/// variables to the variable with the least variable id. It is used when +/// normlizing projections to avoid hitting the recursion limit by creating +/// many versions of a predicate for types that in the end have to unify. +/// +/// If you want to resolve type and const variables as well, call +/// [InferCtxt::resolve_vars_if_possible] first. +pub struct OpportunisticRegionResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, } -impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> { +impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self { - OpportunisticTypeAndRegionResolver { infcx } + OpportunisticRegionResolver { infcx } } } -impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx> { +impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_infer() { + if !t.has_infer_regions() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else { - let t0 = self.infcx.shallow_resolve(t); - t0.super_fold_with(self) + t.super_fold_with(self) } } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReVar(rid) => self - .infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(self.tcx(), rid), + ty::ReVar(rid) => { + let resolved = self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(rid); + if resolved == rid { r } else { self.tcx().mk_region(ty::ReVar(resolved)) } + } _ => r, } } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if !ct.needs_infer() { + if !ct.has_infer_regions() { ct // micro-optimize -- if there is nothing in this const that this fold affects... } else { - let c0 = self.infcx.shallow_resolve(ct); - c0.super_fold_with(self) + ct.super_fold_with(self) } } } diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 248dd00ef47..24dbf7b8c46 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -87,6 +87,9 @@ fn references_error(&self) -> bool { fn has_param_types_or_consts(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) } + fn has_infer_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_INFER) + } fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 9492c3c3409..bccd903f57e 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -24,6 +24,7 @@ use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem}; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::util::IntTypeExt; @@ -1146,7 +1147,7 @@ fn confirm_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); - match candidate { + let mut progress = match candidate { ProjectionTyCandidate::ParamEnv(poly_projection) | ProjectionTyCandidate::TraitDef(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection) @@ -1155,7 +1156,16 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionTyCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source) } + }; + // When checking for cycle during evaluation, we compare predicates with + // "syntactic" equality. Since normalization generally introduces a type + // with new region variables, we need to resolve them to existing variables + // when possible for this to work. See `auto-trait-projection-recursion.rs` + // for a case where this matters. + if progress.ty.has_infer_regions() { + progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty); } + progress } fn confirm_select_candidate<'cx, 'tcx>( diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 137cb83ccd3..0a05fc6bb82 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/project-fn-ret-invariant.rs:48:8 + --> $DIR/project-fn-ret-invariant.rs:48:4 | LL | bar(foo, x) - | ^^^ + | ^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... --> $DIR/project-fn-ret-invariant.rs:44:8 diff --git a/src/test/ui/auto-is-contextual.rs b/src/test/ui/auto-is-contextual.rs deleted file mode 100644 index a2ddd5374c0..00000000000 --- a/src/test/ui/auto-is-contextual.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass - -#![allow(path_statements)] -#![allow(dead_code)] -macro_rules! auto { - () => (struct S;) -} - -auto!(); - -fn auto() {} - -fn main() { - auto(); - let auto = 10; - auto; - auto as u8; -} diff --git a/src/test/ui/auto-trait-validation.rs b/src/test/ui/auto-trait-validation.rs deleted file mode 100644 index 34d6c3da00e..00000000000 --- a/src/test/ui/auto-trait-validation.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(optin_builtin_traits)] - -auto trait Generic {} -//~^ auto traits cannot have generic parameters [E0567] -auto trait Bound : Copy {} -//~^ auto traits cannot have super traits [E0568] -auto trait MyTrait { fn foo() {} } -//~^ auto traits cannot have methods or associated items [E0380] -fn main() {} diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr deleted file mode 100644 index 4040e66c6af..00000000000 --- a/src/test/ui/auto-trait-validation.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:3:19 - | -LL | auto trait Generic {} - | -------^^^ help: remove the parameters - | | - | auto trait cannot have generic parameters - -error[E0568]: auto traits cannot have super traits - --> $DIR/auto-trait-validation.rs:5:20 - | -LL | auto trait Bound : Copy {} - | ----- ^^^^ help: remove the super traits - | | - | auto trait cannot have super traits - -error[E0380]: auto traits cannot have methods or associated items - --> $DIR/auto-trait-validation.rs:7:25 - | -LL | auto trait MyTrait { fn foo() {} } - | ------- ^^^ - | | - | auto trait cannot have items - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0380, E0567, E0568. -For more information about an error, try `rustc --explain E0380`. diff --git a/src/test/ui/auto-traits/auto-is-contextual.rs b/src/test/ui/auto-traits/auto-is-contextual.rs new file mode 100644 index 00000000000..a2ddd5374c0 --- /dev/null +++ b/src/test/ui/auto-traits/auto-is-contextual.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +macro_rules! auto { + () => (struct S;) +} + +auto!(); + +fn auto() {} + +fn main() { + auto(); + let auto = 10; + auto; + auto as u8; +} diff --git a/src/test/ui/auto-traits/auto-trait-projection-recursion.rs b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs new file mode 100644 index 00000000000..a36f26f02e9 --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs @@ -0,0 +1,34 @@ +// Checking the `Send` bound in `main` requires: +// +// checking as Y>::P: Send +// which normalizes to Box>>: Send +// which needs X>: Send +// which needs as Y>::P: Send +// +// At this point we used to normalize the predicate to `Box>>: Send` +// and continue in a loop where we created new region variables to the +// recursion limit. To avoid this we now "canonicalize" region variables to +// lowest unified region vid. This means we instead have to prove +// `Box>>: Send`, which we can because auto traits are coinductive. + +// check-pass + +// Avoid a really long error message if this regresses. +#![recursion_limit="20"] + +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +fn is_send() {} + +fn main() { + is_send::>>(); +} diff --git a/src/test/ui/auto-traits/auto-trait-validation.rs b/src/test/ui/auto-traits/auto-trait-validation.rs new file mode 100644 index 00000000000..34d6c3da00e --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-validation.rs @@ -0,0 +1,9 @@ +#![feature(optin_builtin_traits)] + +auto trait Generic {} +//~^ auto traits cannot have generic parameters [E0567] +auto trait Bound : Copy {} +//~^ auto traits cannot have super traits [E0568] +auto trait MyTrait { fn foo() {} } +//~^ auto traits cannot have methods or associated items [E0380] +fn main() {} diff --git a/src/test/ui/auto-traits/auto-trait-validation.stderr b/src/test/ui/auto-traits/auto-trait-validation.stderr new file mode 100644 index 00000000000..4040e66c6af --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-validation.stderr @@ -0,0 +1,28 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/auto-trait-validation.rs:3:19 + | +LL | auto trait Generic {} + | -------^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error[E0568]: auto traits cannot have super traits + --> $DIR/auto-trait-validation.rs:5:20 + | +LL | auto trait Bound : Copy {} + | ----- ^^^^ help: remove the super traits + | | + | auto trait cannot have super traits + +error[E0380]: auto traits cannot have methods or associated items + --> $DIR/auto-trait-validation.rs:7:25 + | +LL | auto trait MyTrait { fn foo() {} } + | ------- ^^^ + | | + | auto trait cannot have items + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0380, E0567, E0568. +For more information about an error, try `rustc --explain E0380`. diff --git a/src/test/ui/auto-traits/auto-traits.rs b/src/test/ui/auto-traits/auto-traits.rs new file mode 100644 index 00000000000..15fdddc5f3f --- /dev/null +++ b/src/test/ui/auto-traits/auto-traits.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_doc_comments)] +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait Auto {} +unsafe auto trait AutoUnsafe {} + +impl !Auto for bool {} +impl !AutoUnsafe for bool {} + +struct AutoBool(bool); + +impl Auto for AutoBool {} +unsafe impl AutoUnsafe for AutoBool {} + +fn take_auto(_: T) {} +fn take_auto_unsafe(_: T) {} + +fn main() { + // Parse inside functions. + auto trait AutoInner {} + unsafe auto trait AutoUnsafeInner {} + + take_auto(0); + take_auto(AutoBool(true)); + take_auto_unsafe(0); + take_auto_unsafe(AutoBool(true)); + + /// Auto traits are allowed in trait object bounds. + let _: &(dyn Send + Auto) = &0; +} diff --git a/src/test/ui/auto-traits/issue-23080-2.rs b/src/test/ui/auto-traits/issue-23080-2.rs new file mode 100644 index 00000000000..7f6b9e3fba7 --- /dev/null +++ b/src/test/ui/auto-traits/issue-23080-2.rs @@ -0,0 +1,15 @@ +//~ ERROR + +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +unsafe auto trait Trait { + type Output; //~ ERROR E0380 +} + +fn call_method(x: T) {} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/ui/auto-traits/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr new file mode 100644 index 00000000000..48ce09aaa34 --- /dev/null +++ b/src/test/ui/auto-traits/issue-23080-2.stderr @@ -0,0 +1,17 @@ +error[E0380]: auto traits cannot have methods or associated items + --> $DIR/issue-23080-2.rs:7:10 + | +LL | unsafe auto trait Trait { + | ----- auto trait cannot have items +LL | type Output; + | ^^^^^^ + +error[E0275]: overflow evaluating the requirement `<() as Trait>::Output` + | + = note: required because of the requirements on the impl of `Trait` for `()` + = note: required because of the requirements on the impl of `Trait` for `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0275, E0380. +For more information about an error, try `rustc --explain E0275`. diff --git a/src/test/ui/auto-traits/issue-23080.rs b/src/test/ui/auto-traits/issue-23080.rs new file mode 100644 index 00000000000..035db82ba5d --- /dev/null +++ b/src/test/ui/auto-traits/issue-23080.rs @@ -0,0 +1,17 @@ +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +unsafe auto trait Trait { + fn method(&self) { //~ ERROR E0380 + println!("Hello"); + } +} + +fn call_method(x: T) { + x.method(); +} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/ui/auto-traits/issue-23080.stderr b/src/test/ui/auto-traits/issue-23080.stderr new file mode 100644 index 00000000000..73ecb1c362e --- /dev/null +++ b/src/test/ui/auto-traits/issue-23080.stderr @@ -0,0 +1,11 @@ +error[E0380]: auto traits cannot have methods or associated items + --> $DIR/issue-23080.rs:5:8 + | +LL | unsafe auto trait Trait { + | ----- auto trait cannot have items +LL | fn method(&self) { + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0380`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs new file mode 100644 index 00000000000..8824a6d2767 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -0,0 +1,15 @@ +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr new file mode 100644 index 00000000000..63b3300f6db --- /dev/null +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 + | +LL | auto trait Magic : Sized where Option : Magic {} + | ----- ^^^^^ help: remove the super traits + | | + | auto trait cannot have super traits + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs new file mode 100644 index 00000000000..edbca915124 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs @@ -0,0 +1,39 @@ +// This test is for #29859, we need to ensure auto traits, +// (also known previously as default traits), do not have +// supertraits. Since the compiler synthesizes these +// instances on demand, we are essentially enabling +// users to write axioms if we view trait selection, +// as a proof system. +// +// For example the below test allows us to add the rule: +// forall (T : Type), T : Copy +// +// Providing a copy instance for *any* type, which +// is most definitely unsound. Imagine copying a +// type that contains a mutable reference, enabling +// mutable aliasing. +// +// You can imagine an even more dangerous test, +// which currently compiles on nightly. +// +// fn main() { +// let mut i = 10; +// let (a, b) = copy(&mut i); +// println!("{:?} {:?}", a, b); +// } + +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait Magic: Copy {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr new file mode 100644 index 00000000000..796638fc54d --- /dev/null +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 + | +LL | auto trait Magic: Copy {} + | ----- ^^^^ help: remove the super traits + | | + | auto trait cannot have super traits + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs new file mode 100644 index 00000000000..71ac2b466c1 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs @@ -0,0 +1,19 @@ +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::<(MyS2, MyS)>(); + //~^ ERROR `MyS2: MyTrait` is not satisfied +} diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr new file mode 100644 index 00000000000..53ba9b8a3f6 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` + --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5 + | +LL | fn is_mytrait() {} + | ------- required by this bound in `is_mytrait` +... +LL | is_mytrait::<(MyS2, MyS)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` + | + = help: the following implementations were found: + + = note: required because it appears within the type `(MyS2, MyS)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs new file mode 100644 index 00000000000..6483b9213dc --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs @@ -0,0 +1,23 @@ +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +impl !MyTrait for *mut T {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +struct MyS3; + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::(); + //~^ ERROR `MyS2: MyTrait` is not satisfied +} diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr new file mode 100644 index 00000000000..bc500004984 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-constituent-types.rs:21:18 + | +LL | fn is_mytrait() {} + | ------- required by this bound in `is_mytrait` +... +LL | is_mytrait::(); + | ^^^^ the trait `MyTrait` is not implemented for `MyS2` + | + = help: the following implementations were found: + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs new file mode 100644 index 00000000000..47cab60625d --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs @@ -0,0 +1,29 @@ +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +unsafe auto trait MyUnsafeTrait {} + +struct ThisImplsTrait; + +impl !MyUnsafeTrait for ThisImplsTrait {} + + +struct ThisImplsUnsafeTrait; + +impl !MyTrait for ThisImplsUnsafeTrait {} + +fn is_my_trait() {} +fn is_my_unsafe_trait() {} + +fn main() { + is_my_trait::(); + is_my_trait::(); + //~^ ERROR `ThisImplsUnsafeTrait: MyTrait` is not satisfied + + is_my_unsafe_trait::(); + //~^ ERROR `ThisImplsTrait: MyUnsafeTrait` is not satisfied + + is_my_unsafe_trait::(); +} diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr new file mode 100644 index 00000000000..76a6994cb00 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-negation.rs:22:19 + | +LL | fn is_my_trait() {} + | ------- required by this bound in `is_my_trait` +... +LL | is_my_trait::(); + | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` + | + = help: the following implementations were found: + + +error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-negation.rs:25:26 + | +LL | fn is_my_unsafe_trait() {} + | ------------- required by this bound in `is_my_unsafe_trait` +... +LL | is_my_unsafe_trait::(); + | ^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` + | + = help: the following implementations were found: + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs new file mode 100644 index 00000000000..614a5ff55b1 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs @@ -0,0 +1,21 @@ +// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies +// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In +// other words, the auto impl only applies if there are no existing +// impls whose types unify. + +#![feature(optin_builtin_traits)] +#![feature(negative_impls)] + +auto trait Defaulted { } +impl<'a,T:Signed> Defaulted for &'a T { } +impl<'a,T:Signed> Defaulted for &'a mut T { } +fn is_defaulted() { } + +trait Signed { } +impl Signed for i32 { } + +fn main() { + is_defaulted::<&'static i32>(); + is_defaulted::<&'static u32>(); + //~^ ERROR `u32: Signed` is not satisfied +} diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr new file mode 100644 index 00000000000..5962d191292 --- /dev/null +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `u32: Signed` is not satisfied + --> $DIR/typeck-default-trait-impl-precedence.rs:19:5 + | +LL | fn is_defaulted() { } + | --------- required by this bound in `is_defaulted` +... +LL | is_defaulted::<&'static u32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` + | + = note: required because of the requirements on the impl of `Defaulted` for `&'static u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs deleted file mode 100644 index 7f6b9e3fba7..00000000000 --- a/src/test/ui/issues/issue-23080-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -//~ ERROR - -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -unsafe auto trait Trait { - type Output; //~ ERROR E0380 -} - -fn call_method(x: T) {} - -fn main() { - // ICE - call_method(()); -} diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr deleted file mode 100644 index 48ce09aaa34..00000000000 --- a/src/test/ui/issues/issue-23080-2.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080-2.rs:7:10 - | -LL | unsafe auto trait Trait { - | ----- auto trait cannot have items -LL | type Output; - | ^^^^^^ - -error[E0275]: overflow evaluating the requirement `<() as Trait>::Output` - | - = note: required because of the requirements on the impl of `Trait` for `()` - = note: required because of the requirements on the impl of `Trait` for `()` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0275, E0380. -For more information about an error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs deleted file mode 100644 index 035db82ba5d..00000000000 --- a/src/test/ui/issues/issue-23080.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -unsafe auto trait Trait { - fn method(&self) { //~ ERROR E0380 - println!("Hello"); - } -} - -fn call_method(x: T) { - x.method(); -} - -fn main() { - // ICE - call_method(()); -} diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr deleted file mode 100644 index 73ecb1c362e..00000000000 --- a/src/test/ui/issues/issue-23080.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080.rs:5:8 - | -LL | unsafe auto trait Trait { - | ----- auto trait cannot have items -LL | fn method(&self) { - | ^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0380`. diff --git a/src/test/ui/traits/auto-traits.rs b/src/test/ui/traits/auto-traits.rs deleted file mode 100644 index 15fdddc5f3f..00000000000 --- a/src/test/ui/traits/auto-traits.rs +++ /dev/null @@ -1,32 +0,0 @@ -// run-pass -#![allow(unused_doc_comments)] -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait Auto {} -unsafe auto trait AutoUnsafe {} - -impl !Auto for bool {} -impl !AutoUnsafe for bool {} - -struct AutoBool(bool); - -impl Auto for AutoBool {} -unsafe impl AutoUnsafe for AutoBool {} - -fn take_auto(_: T) {} -fn take_auto_unsafe(_: T) {} - -fn main() { - // Parse inside functions. - auto trait AutoInner {} - unsafe auto trait AutoUnsafeInner {} - - take_auto(0); - take_auto(AutoBool(true)); - take_auto_unsafe(0); - take_auto_unsafe(AutoBool(true)); - - /// Auto traits are allowed in trait object bounds. - let _: &(dyn Send + Auto) = &0; -} diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.rs b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs new file mode 100644 index 00000000000..205d50a2ed9 --- /dev/null +++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs @@ -0,0 +1,30 @@ +// Test that we don't hit the recursion limit for short cycles involving lifetimes. + +// Shouldn't hit this, we should realize that we're in a cycle sooner. +#![recursion_limit="20"] + +trait NotAuto {} +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +impl NotAuto for Box {} +impl NotAuto for X where T::P: NotAuto {} +impl<'a> NotAuto for C<'a> {} + +fn is_send() {} +//~^ NOTE: required + +fn main() { + // Should only be a few notes. + is_send::>>(); + //~^ ERROR overflow evaluating + //~| NOTE: required +} diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr new file mode 100644 index 00000000000..9a227229ea4 --- /dev/null +++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `std::boxed::Box>>: NotAuto` + --> $DIR/traits-inductive-overflow-lifetime.rs:27:5 + | +LL | fn is_send() {} + | ------- required by this bound in `is_send` +... +LL | is_send::>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `NotAuto` for `X>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs deleted file mode 100644 index 8824a6d2767..00000000000 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 -impl Magic for T {} - -fn copy(x: T) -> (T, T) { (x, x) } - -#[derive(Debug)] -struct NoClone; - -fn main() { - let (a, b) = copy(NoClone); - println!("{:?} {:?}", a, b); -} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr deleted file mode 100644 index 63b3300f6db..00000000000 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 - | -LL | auto trait Magic : Sized where Option : Magic {} - | ----- ^^^^^ help: remove the super traits - | | - | auto trait cannot have super traits - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs deleted file mode 100644 index edbca915124..00000000000 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs +++ /dev/null @@ -1,39 +0,0 @@ -// This test is for #29859, we need to ensure auto traits, -// (also known previously as default traits), do not have -// supertraits. Since the compiler synthesizes these -// instances on demand, we are essentially enabling -// users to write axioms if we view trait selection, -// as a proof system. -// -// For example the below test allows us to add the rule: -// forall (T : Type), T : Copy -// -// Providing a copy instance for *any* type, which -// is most definitely unsound. Imagine copying a -// type that contains a mutable reference, enabling -// mutable aliasing. -// -// You can imagine an even more dangerous test, -// which currently compiles on nightly. -// -// fn main() { -// let mut i = 10; -// let (a, b) = copy(&mut i); -// println!("{:?} {:?}", a, b); -// } - -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait Magic: Copy {} //~ ERROR E0568 -impl Magic for T {} - -fn copy(x: T) -> (T, T) { (x, x) } - -#[derive(Debug)] -struct NoClone; - -fn main() { - let (a, b) = copy(NoClone); - println!("{:?} {:?}", a, b); -} diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr deleted file mode 100644 index 796638fc54d..00000000000 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 - | -LL | auto trait Magic: Copy {} - | ----- ^^^^ help: remove the super traits - | | - | auto trait cannot have super traits - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs deleted file mode 100644 index 71ac2b466c1..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait MyTrait {} - -struct MyS; - -struct MyS2; - -impl !MyTrait for MyS2 {} - -fn is_mytrait() {} - -fn main() { - is_mytrait::(); - - is_mytrait::<(MyS2, MyS)>(); - //~^ ERROR `MyS2: MyTrait` is not satisfied -} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr deleted file mode 100644 index 53ba9b8a3f6..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` - --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5 - | -LL | fn is_mytrait() {} - | ------- required by this bound in `is_mytrait` -... -LL | is_mytrait::<(MyS2, MyS)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` - | - = help: the following implementations were found: - - = note: required because it appears within the type `(MyS2, MyS)` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs deleted file mode 100644 index 6483b9213dc..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait MyTrait {} - -impl !MyTrait for *mut T {} - -struct MyS; - -struct MyS2; - -impl !MyTrait for MyS2 {} - -struct MyS3; - -fn is_mytrait() {} - -fn main() { - is_mytrait::(); - - is_mytrait::(); - //~^ ERROR `MyS2: MyTrait` is not satisfied -} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr deleted file mode 100644 index bc500004984..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-constituent-types.rs:21:18 - | -LL | fn is_mytrait() {} - | ------- required by this bound in `is_mytrait` -... -LL | is_mytrait::(); - | ^^^^ the trait `MyTrait` is not implemented for `MyS2` - | - = help: the following implementations were found: - - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/typeck/typeck-default-trait-impl-negation.rs deleted file mode 100644 index 47cab60625d..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait MyTrait {} - -unsafe auto trait MyUnsafeTrait {} - -struct ThisImplsTrait; - -impl !MyUnsafeTrait for ThisImplsTrait {} - - -struct ThisImplsUnsafeTrait; - -impl !MyTrait for ThisImplsUnsafeTrait {} - -fn is_my_trait() {} -fn is_my_unsafe_trait() {} - -fn main() { - is_my_trait::(); - is_my_trait::(); - //~^ ERROR `ThisImplsUnsafeTrait: MyTrait` is not satisfied - - is_my_unsafe_trait::(); - //~^ ERROR `ThisImplsTrait: MyUnsafeTrait` is not satisfied - - is_my_unsafe_trait::(); -} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr deleted file mode 100644 index 76a6994cb00..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:22:19 - | -LL | fn is_my_trait() {} - | ------- required by this bound in `is_my_trait` -... -LL | is_my_trait::(); - | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` - | - = help: the following implementations were found: - - -error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied - --> $DIR/typeck-default-trait-impl-negation.rs:25:26 - | -LL | fn is_my_unsafe_trait() {} - | ------------- required by this bound in `is_my_unsafe_trait` -... -LL | is_my_unsafe_trait::(); - | ^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` - | - = help: the following implementations were found: - - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs deleted file mode 100644 index 614a5ff55b1..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies -// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In -// other words, the auto impl only applies if there are no existing -// impls whose types unify. - -#![feature(optin_builtin_traits)] -#![feature(negative_impls)] - -auto trait Defaulted { } -impl<'a,T:Signed> Defaulted for &'a T { } -impl<'a,T:Signed> Defaulted for &'a mut T { } -fn is_defaulted() { } - -trait Signed { } -impl Signed for i32 { } - -fn main() { - is_defaulted::<&'static i32>(); - is_defaulted::<&'static u32>(); - //~^ ERROR `u32: Signed` is not satisfied -} diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr deleted file mode 100644 index 5962d191292..00000000000 --- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: the trait bound `u32: Signed` is not satisfied - --> $DIR/typeck-default-trait-impl-precedence.rs:19:5 - | -LL | fn is_defaulted() { } - | --------- required by this bound in `is_defaulted` -... -LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` - | - = note: required because of the requirements on the impl of `Defaulted` for `&'static u32` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`.