diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index c15915a9d561f..67d35253404b0 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -358,19 +358,21 @@ impl<'tcx> TraitAliasExpander<'tcx> { debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); // Don't recurse if this bound is not a trait alias. - let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias { + if !tcx.is_trait_alias(trait_ref.def_id()) { return true; } // Don't recurse if this trait alias is already on the stack for the DFS search. let anon_pred = anonymize_predicate(tcx, &pred); - if item.path.iter().rev().skip(1) - .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) { + if item.path.iter() + .rev() + .skip(1) + .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) + { return false; } - // Get components of trait alias. + // Get the components of this trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); let items = predicates.predicates diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a33b2e32c8658..3c15e654ddeff 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2,7 +2,6 @@ //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. -use errors::{Applicability, DiagnosticId}; use crate::hir::{self, GenericArg, GenericArgs, ExprKind}; use crate::hir::def::{CtorOf, Res, DefKind}; use crate::hir::def_id::DefId; @@ -12,6 +11,10 @@ use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; use crate::namespace::Namespace; +use crate::require_c_abi_if_c_variadic; +use crate::util::common::ErrorReported; +use crate::util::nodemap::FxHashMap; + use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, Const, ToPredicate, TypeFoldable}; @@ -19,25 +22,23 @@ use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{self, Subst, InternalSubsts, SubstsRef}; use rustc::ty::wf::object_region_bounds; use rustc_target::spec::abi; -use crate::require_c_abi_if_c_variadic; -use smallvec::SmallVec; + use syntax::ast; use syntax::errors::pluralize; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, Span, MultiSpan}; -use crate::util::common::ErrorReported; -use crate::util::nodemap::FxHashMap; + +use errors::{Applicability, DiagnosticId}; +use rustc_data_structures::fx::FxHashSet; +use rustc_error_codes::*; +use smallvec::SmallVec; use std::collections::BTreeSet; use std::iter; use std::slice; -use rustc_data_structures::fx::FxHashSet; - -use rustc_error_codes::*; - #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); @@ -64,8 +65,7 @@ pub trait AstConv<'tcx> { &self, param: Option<&ty::GenericParamDef>, span: Span, - ) - -> Option>; + ) -> Option>; /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; @@ -1247,8 +1247,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. let expanded_traits = - traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned()); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned()) + // Ensure that trait ref is to self type and not some type param. + .filter(|info| info.trait_ref().self_ty() == dummy_self); + let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; @@ -1289,7 +1291,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut associated_types = BTreeSet::default(); let regular_traits_refs = bounds.trait_bounds - .into_iter() + .iter() + .cloned() .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())) .map(|(trait_ref, _)| trait_ref); for trait_ref in traits::elaborate_trait_refs(tcx, regular_traits_refs) { @@ -1398,50 +1401,53 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.emit(); } + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + bounds.trait_bounds + .into_iter() + .map(|(trait_ref, _)| trait_ref) + .partition(|i| tcx.trait_is_auto(i.def_id())); + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as // `dyn Trait + Send`. - auto_traits.sort_by_key(|i| i.trait_ref().def_id()); - auto_traits.dedup_by_key(|i| i.trait_ref().def_id()); - debug!("regular_traits: {:?}", regular_traits); - debug!("auto_traits: {:?}", auto_traits); + auto_traits.sort_by_key(|i| i.def_id()); + auto_traits.dedup_by_key(|i| i.def_id()); + debug!( + "conv_object_ty_poly_trait_ref: regular_traits={:?} auto_traits={:?}", + regular_traits, auto_traits + ); // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by // removing the dummy `Self` type (`trait_object_dummy_self`). let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| { if trait_ref.self_ty() != dummy_self { - // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`, - // which picks up non-supertraits where clauses - but also, the object safety - // completely ignores trait aliases, which could be object safety hazards. We - // `delay_span_bug` here to avoid an ICE in stable even when the feature is - // disabled. (#66420) - tcx.sess.delay_span_bug(DUMMY_SP, &format!( - "trait_ref_to_existential called on {:?} with non-dummy Self", - trait_ref, - )); + bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref); } ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) }; // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref| trait_ref_to_existential(trait_ref)) - }); - let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { - bound.map_bound(|b| { - let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); - ty::ExistentialProjection { - ty: b.ty, - item_def_id: b.projection_ty.item_def_id, - substs: trait_ref.substs, - } - }) - }); + let existential_trait_refs = regular_traits + .iter() + .map(|i| i.map_bound(|trait_ref| trait_ref_to_existential(trait_ref))); + let existential_projections = bounds.projection_bounds + .iter() + .map(|(bound, _)| { + bound.map_bound(|b| { + let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); + ty::ExistentialProjection { + ty: b.ty, + item_def_id: b.projection_ty.item_def_id, + substs: trait_ref.substs, + } + }) + }); // Calling `skip_binder` is okay because the predicates are re-bound. - let regular_trait_predicates = existential_trait_refs.map( - |trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); - let auto_trait_predicates = auto_traits.into_iter().map( - |trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())); + let regular_trait_predicates = existential_trait_refs + .map(|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); + let auto_trait_predicates = auto_traits + .into_iter() + .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.def_id())); let mut v = regular_trait_predicates .chain(auto_trait_predicates) @@ -1469,10 +1475,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }) }; - debug!("region_bound: {:?}", region_bound); + debug!("conv_object_ty_poly_trait_ref: region_bound={:?}", region_bound); let ty = tcx.mk_dynamic(existential_predicates, region_bound); - debug!("trait_object_type: {:?}", ty); + debug!("conv_object_ty_poly_trait_ref: trait_object_type={:?}", ty); ty } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 82c0eba87ef3d..6d4c2eee2594a 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving ` as std::iter::It LL | let _: &dyn I32Iterator = &vec![42].into_iter(); | ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | - = note: required for the cast to the object type `dyn std::iter::Iterator` + = note: required for the cast to the object type `dyn I32Iterator` error: aborting due to previous error diff --git a/src/test/ui/bad/bad-sized.rs b/src/test/ui/bad/bad-sized.rs index b899c59ff2ea7..a8734fede592a 100644 --- a/src/test/ui/bad/bad-sized.rs +++ b/src/test/ui/bad/bad-sized.rs @@ -1,8 +1,12 @@ +// ignore-tidy-linelength + trait Trait {} pub fn main() { let x: Vec = Vec::new(); - //~^ ERROR only auto traits can be used as additional traits in a trait object - //~| ERROR the size for values of type - //~| ERROR the size for values of type + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + //~| ERROR the size for values of type `dyn std::marker::Sized` cannot be known at compilation time [E0277] + //~| the trait `std::marker::Sized` cannot be made into an object [E0038] + //~| ERROR the size for values of type `dyn std::marker::Sized` cannot be known at compilation time [E0277] + //~| the trait `std::marker::Sized` cannot be made into an object [E0038] } diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index e9ded557281a4..80073dd51d63a 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -1,5 +1,5 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/bad-sized.rs:4:28 + --> $DIR/bad-sized.rs:6:28 | LL | let x: Vec = Vec::new(); | ----- ^^^^^ @@ -9,27 +9,43 @@ LL | let x: Vec = Vec::new(); | first non-auto trait | trait alias used in trait object type (first use) -error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time - --> $DIR/bad-sized.rs:4:12 +error[E0277]: the size for values of type `dyn std::marker::Sized` cannot be known at compilation time + --> $DIR/bad-sized.rs:6:12 | LL | let x: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `dyn Trait` + = help: the trait `std::marker::Sized` is not implemented for `dyn std::marker::Sized` = note: to learn more, visit = note: required by `std::vec::Vec` -error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time - --> $DIR/bad-sized.rs:4:37 +error[E0038]: the trait `std::marker::Sized` cannot be made into an object + --> $DIR/bad-sized.rs:6:12 + | +LL | let x: Vec = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Sized` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error[E0277]: the size for values of type `dyn std::marker::Sized` cannot be known at compilation time + --> $DIR/bad-sized.rs:6:37 | LL | let x: Vec = Vec::new(); | ^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `dyn Trait` + = help: the trait `std::marker::Sized` is not implemented for `dyn std::marker::Sized` = note: to learn more, visit = note: required by `std::vec::Vec::::new` -error: aborting due to 3 previous errors +error[E0038]: the trait `std::marker::Sized` cannot be made into an object + --> $DIR/bad-sized.rs:6:37 + | +LL | let x: Vec = Vec::new(); + | ^^^^^^^^ the trait `std::marker::Sized` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0225, E0277. -For more information about an error, try `rustc --explain E0225`. +Some errors have detailed explanations: E0038, E0225, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/issues/issue-32963.rs b/src/test/ui/issues/issue-32963.rs index ee099069f0241..379c10feab7b6 100644 --- a/src/test/ui/issues/issue-32963.rs +++ b/src/test/ui/issues/issue-32963.rs @@ -2,10 +2,11 @@ use std::mem; trait Misc {} -fn size_of_copy() -> usize { mem::size_of::() } +fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_copy::(); - //~^ ERROR only auto traits can be used as additional traits in a trait object - //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + //~| ERROR the trait bound `dyn std::marker::Copy: std::marker::Copy` is not satisfied [E0277] + //~| ERROR the trait `std::marker::Copy` cannot be made into an object [E0038] } diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index e3564e8670174..d824689f0c524 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -9,16 +9,24 @@ LL | size_of_copy::(); | first non-auto trait | trait alias used in trait object type (first use) -error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied +error[E0277]: the trait bound `dyn std::marker::Copy: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 | -LL | fn size_of_copy() -> usize { mem::size_of::() } +LL | fn size_of_copy() -> usize { mem::size_of::() } | ------------ ---- required by this bound in `size_of_copy` ... LL | size_of_copy::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn std::marker::Copy` -error: aborting due to 2 previous errors +error[E0038]: the trait `std::marker::Copy` cannot be made into an object + --> $DIR/issue-32963.rs:8:20 + | +LL | size_of_copy::(); + | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0225, E0277. -For more information about an error, try `rustc --explain E0225`. +Some errors have detailed explanations: E0038, E0225, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/issues/issue-65673.rs b/src/test/ui/issues/issue-65673.rs deleted file mode 100644 index 4b47bd493a568..0000000000000 --- a/src/test/ui/issues/issue-65673.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled. -trait Trait {} -trait WithType { - type Ctx; -} -trait Alias = where T: Trait; - -impl WithType for T { - type Ctx = dyn Alias; -//~^ ERROR the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time -} -fn main() {} diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/issues/issue-65673.stderr deleted file mode 100644 index a556e35b6a944..0000000000000 --- a/src/test/ui/issues/issue-65673.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/issue-65673.rs:9:5 - | -LL | type Ctx; - | --- associated type defined here -... -LL | impl WithType for T { - | ---------------------- in this `impl` item -LL | type Ctx = dyn Alias; - | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)` - = note: to learn more, visit - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs deleted file mode 100644 index 9e412215512c9..0000000000000 --- a/src/test/ui/traits/auxiliary/trait_alias.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(trait_alias)] - -pub trait Hello { - fn hello(&self); -} - -pub struct Hi; - -impl Hello for Hi { - fn hello(&self) {} -} - -pub trait Greet = Hello; diff --git a/src/test/ui/traits/trait-alias-import-cross-crate.rs b/src/test/ui/traits/trait-alias-import-cross-crate.rs deleted file mode 100644 index 975542ab49b59..0000000000000 --- a/src/test/ui/traits/trait-alias-import-cross-crate.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass -// aux-build:trait_alias.rs - -#![feature(trait_alias)] - -extern crate trait_alias; - -// Import only the alias, not the real trait. -use trait_alias::{Greet, Hi}; - -fn main() { - let hi = Hi; - hi.hello(); // From `Hello`, via `Greet` alias. -} diff --git a/src/test/ui/traits/trait-alias/issue-65673-fail.rs b/src/test/ui/traits/trait-alias/issue-65673-fail.rs new file mode 100644 index 0000000000000..9ffa43b28cd59 --- /dev/null +++ b/src/test/ui/traits/trait-alias/issue-65673-fail.rs @@ -0,0 +1,22 @@ +#![feature(trait_alias)] + +use std::any::Any; + +trait Trait {} + +trait WithType { + type Ctx: ?Sized; +} + +trait Alias = Any where T: Trait; + +// Note, we do not impl `Trait` for `()` here, so should expect the error below. + +impl WithType for T { + type Ctx = dyn Alias; +} + +fn main() { + let _: Box<<() as WithType>::Ctx> = Box::new(()); + //~^ ERROR the trait bound `(): Trait` is not satisfied [E0277] +} diff --git a/src/test/ui/traits/trait-alias/issue-65673-fail.stderr b/src/test/ui/traits/trait-alias/issue-65673-fail.stderr new file mode 100644 index 0000000000000..b6cca0e5189d3 --- /dev/null +++ b/src/test/ui/traits/trait-alias/issue-65673-fail.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `(): Trait` is not satisfied + --> $DIR/issue-65673-fail.rs:20:41 + | +LL | let _: Box<<() as WithType>::Ctx> = Box::new(()); + | ^^^^^^^^^^^^ the trait `Trait` is not implemented for `()` + | + = note: required for the cast to the object type `dyn Alias<()>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-alias/issue-65673.rs b/src/test/ui/traits/trait-alias/issue-65673.rs new file mode 100644 index 0000000000000..85a6ff1e3823f --- /dev/null +++ b/src/test/ui/traits/trait-alias/issue-65673.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(trait_alias)] + +use std::any::Any; + +trait Trait {} + +trait WithType { + type Ctx: ?Sized; +} + +trait Alias = Any where T: Trait; + +impl Trait for () {} + +impl WithType for T { + type Ctx = dyn Alias; +} + +fn main() { + let _: Box<<() as WithType>::Ctx> = Box::new(()); +} diff --git a/src/test/ui/traits/trait-alias-ambiguous.rs b/src/test/ui/traits/trait-alias/trait-alias-ambiguous.rs similarity index 100% rename from src/test/ui/traits/trait-alias-ambiguous.rs rename to src/test/ui/traits/trait-alias/trait-alias-ambiguous.rs diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias/trait-alias-ambiguous.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-ambiguous.stderr rename to src/test/ui/traits/trait-alias/trait-alias-ambiguous.stderr diff --git a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias/trait-alias-import-cross-crate.rs similarity index 100% rename from src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs rename to src/test/ui/traits/trait-alias/trait-alias-import-cross-crate.rs diff --git a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-import-cross-crate.stderr similarity index 89% rename from src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr rename to src/test/ui/traits/trait-alias/trait-alias-import-cross-crate.stderr index cad5c81f5a6ca..4f84dabf4e4fd 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-import-cross-crate.stderr @@ -1,5 +1,5 @@ error[E0277]: `std::rc::Rc` cannot be sent between threads safely - --> $DIR/trait-alias-cross-crate.rs:14:17 + --> $DIR/trait-alias-import-cross-crate.rs:14:17 | LL | fn use_alias() {} | --------- -------- required by this bound in `use_alias` @@ -10,7 +10,7 @@ LL | use_alias::>(); = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc` error[E0277]: `std::rc::Rc` cannot be shared between threads safely - --> $DIR/trait-alias-cross-crate.rs:14:17 + --> $DIR/trait-alias-import-cross-crate.rs:14:17 | LL | fn use_alias() {} | --------- -------- required by this bound in `use_alias` diff --git a/src/test/ui/traits/trait-alias-import.rs b/src/test/ui/traits/trait-alias/trait-alias-import.rs similarity index 100% rename from src/test/ui/traits/trait-alias-import.rs rename to src/test/ui/traits/trait-alias/trait-alias-import.rs