diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 00dec3b355f8f..c9b73c682098b 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -670,6 +670,9 @@ pub enum ObjectSafetyViolation { /// Associated const. AssocConst(Symbol, Span), + + /// GAT + GAT(Symbol, Span), } impl ObjectSafetyViolation { @@ -715,6 +718,9 @@ impl ObjectSafetyViolation { format!("it contains associated `const` `{}`", name).into() } ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), + ObjectSafetyViolation::GAT(name, _) => { + format!("it contains the generic associated type `{}`", name).into() + } } } @@ -773,6 +779,7 @@ impl ObjectSafetyViolation { ); } ObjectSafetyViolation::AssocConst(name, _) + | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { err.help(&format!("consider moving `{}` to another trait", name)); } @@ -786,6 +793,7 @@ impl ObjectSafetyViolation { ObjectSafetyViolation::SupertraitSelf(spans) | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), ObjectSafetyViolation::AssocConst(_, span) + | ObjectSafetyViolation::GAT(_, span) | ObjectSafetyViolation::Method(_, _, span) if *span != DUMMY_SP => { diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index 249f5e835cd78..2041109eb385f 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -717,11 +717,21 @@ pub(super) fn filtered_terminator_span( | TerminatorKind::FalseEdge { .. } | TerminatorKind::Goto { .. } => None, + // Call `func` operand can have a more specific span when part of a chain of calls + | TerminatorKind::Call { ref func, .. } => { + let mut span = terminator.source_info.span; + if let mir::Operand::Constant(box constant) = func { + if constant.span.lo() > span.lo() { + span = span.with_lo(constant.span.lo()); + } + } + Some(function_source_span(span, body_span)) + } + // Retain spans from all other terminators TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Return - | TerminatorKind::Call { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseUnwind { .. } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index ac5ec24eeeeb5..d5e1bd3f9ea2e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -132,6 +132,14 @@ fn object_safety_violations_for_trait( .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)), ); + violations.extend( + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) + .map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)), + ); + debug!( "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, violations diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 31685a012ca2f..e338a21b60308 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -462,12 +462,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for assoc_type in assoc_types { if !tcx.generics_of(assoc_type).params.is_empty() { - // FIXME(generic_associated_types) generate placeholders to - // extend the trait substs. - tcx.sess.span_fatal( + tcx.sess.delay_span_bug( obligation.cause.span, - "generic associated types in trait objects are not supported yet", + "GATs in trait object shouldn't have been considered", ); + return Err(SelectionError::Unimplemented); } // This maybe belongs in wf, but that can't (doesn't) handle // higher-ranked things. diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3a5dcec668ff6..15308a4469bf0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -76,7 +76,6 @@ #![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(new_uninit))] #![feature(allocator_api)] -#![feature(vec_extend_from_within)] #![feature(array_chunks)] #![feature(array_methods)] #![feature(array_windows)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e459442dfcfc5..85c9446689e67 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2124,8 +2124,6 @@ impl Vec { /// ## Examples /// /// ``` - /// #![feature(vec_extend_from_within)] - /// /// let mut vec = vec![0, 1, 2, 3, 4]; /// /// vec.extend_from_within(2..); @@ -2137,7 +2135,7 @@ impl Vec { /// vec.extend_from_within(4..8); /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); /// ``` - #[unstable(feature = "vec_extend_from_within", issue = "81656")] + #[stable(feature = "vec_extend_from_within", since = "1.53.0")] pub fn extend_from_within(&mut self, src: R) where R: RangeBounds, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 7e1194cc4aa20..25a83a0b01438 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -20,7 +20,6 @@ #![feature(vecdeque_binary_search)] #![feature(slice_group_by)] #![feature(slice_partition_dedup)] -#![feature(vec_extend_from_within)] #![feature(vec_spare_capacity)] #![feature(string_remove_matches)] diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 116a37249e392..d20bb58584101 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -752,7 +752,7 @@ pub fn args() -> Args { /// does on macOS and Windows. /// /// Note that the returned iterator will not check if the arguments to the -/// process are valid Unicode. To ensure UTF-8 validity, +/// process are valid Unicode. If you want to panic on invalid UTF-8, /// use the [`args`] function instead. /// /// # Examples diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e39652c6dd5de..45412f55c1572 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -82,6 +82,10 @@ impl Buffer { self.buffer.push_str(s); } + crate fn push_buffer(&mut self, other: Buffer) { + self.buffer.push_str(&other.buffer); + } + // Intended for consumption by write! and writeln! (std::fmt) but without // the fmt::Result return type imposed by fmt::Write (and avoiding the trait // import). diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 19b8dd15ad0f2..518dbc6eeb3b9 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1281,99 +1281,6 @@ fn render_impl( let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]); let mut close_tags = String::new(); - if render_mode == RenderMode::Normal { - let id = cx.derive_id(match i.inner_impl().trait_ { - Some(ref t) => { - if is_on_foreign_type { - get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx) - } else { - format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx)))) - } - } - None => "impl".to_string(), - }); - let aliases = if aliases.is_empty() { - String::new() - } else { - format!(" aliases=\"{}\"", aliases.join(",")) - }; - if let Some(use_absolute) = use_absolute { - write!( - w, - "
\ - \ -

\ - ", - id, aliases - ); - close_tags.insert_str(0, "

"); - write!(w, "{}", i.inner_impl().print(use_absolute, cx)); - if show_def_docs { - for it in &i.inner_impl().items { - if let clean::TypedefItem(ref tydef, _) = *it.kind { - w.write_str(" "); - assoc_type( - w, - it, - &[], - Some(&tydef.type_), - AssocItemLink::Anchor(None), - "", - cx, - ); - w.write_str(";"); - } - } - } - w.write_str(""); - } else { - write!( - w, - "
\ - \ -

\ - {}", - id, - aliases, - i.inner_impl().print(false, cx) - ); - close_tags.insert_str(0, "

"); - } - write!(w, "", id); - render_stability_since_raw( - w, - i.impl_item.stable_since(tcx).as_deref(), - i.impl_item.const_stable_since(tcx).as_deref(), - outer_version, - outer_const_version, - ); - write_srclink(cx, &i.impl_item, w); - w.write_str(""); - - if trait_.is_some() { - if let Some(portability) = portability(&i.impl_item, Some(parent)) { - write!(w, "
{}
", portability); - } - } - - if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { - let mut ids = cx.id_map.borrow_mut(); - write!( - w, - "
{}
", - Markdown( - &*dox, - &i.impl_item.links(cx), - &mut ids, - cx.shared.codes, - cx.shared.edition(), - &cx.shared.playground - ) - .into_string() - ); - } - } - fn doc_impl_item( w: &mut Buffer, cx: &Context<'_>, @@ -1549,11 +1456,10 @@ fn render_impl( } } - w.write_str("
"); - close_tags.insert_str(0, "
"); + let mut impl_items = Buffer::empty_from(w); for trait_item in &i.inner_impl().items { doc_impl_item( - w, + &mut impl_items, cx, trait_item, if trait_.is_some() { &i.impl_item } else { parent }, @@ -1609,7 +1515,7 @@ fn render_impl( if show_default_items { if let Some(t) = trait_ { render_default_items( - w, + &mut impl_items, cx, &t.trait_, &i.inner_impl(), @@ -1621,6 +1527,111 @@ fn render_impl( ); } } + let details_str = if impl_items.is_empty() { + "" + } else { + "
" + }; + if render_mode == RenderMode::Normal { + let id = cx.derive_id(match i.inner_impl().trait_ { + Some(ref t) => { + if is_on_foreign_type { + get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx) + } else { + format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx)))) + } + } + None => "impl".to_string(), + }); + let aliases = if aliases.is_empty() { + String::new() + } else { + format!(" aliases=\"{}\"", aliases.join(",")) + }; + if let Some(use_absolute) = use_absolute { + write!( + w, + "{}

", + details_str, id, aliases + ); + if !impl_items.is_empty() { + close_tags.insert_str(0, "

"); + } + write!(w, "{}", i.inner_impl().print(use_absolute, cx)); + if show_def_docs { + for it in &i.inner_impl().items { + if let clean::TypedefItem(ref tydef, _) = *it.kind { + w.write_str(" "); + assoc_type( + w, + it, + &[], + Some(&tydef.type_), + AssocItemLink::Anchor(None), + "", + cx, + ); + w.write_str(";"); + } + } + } + w.write_str(""); + } else { + write!( + w, + "{}

{}", + details_str, + id, + aliases, + i.inner_impl().print(false, cx) + ); + if !impl_items.is_empty() { + close_tags.insert_str(0, ""); + } + } + write!(w, "", id); + render_stability_since_raw( + w, + i.impl_item.stable_since(tcx).as_deref(), + i.impl_item.const_stable_since(tcx).as_deref(), + outer_version, + outer_const_version, + ); + write_srclink(cx, &i.impl_item, w); + if impl_items.is_empty() { + w.write_str("

"); + } else { + w.write_str(""); + } + + if trait_.is_some() { + if let Some(portability) = portability(&i.impl_item, Some(parent)) { + write!(w, "
{}
", portability); + } + } + + if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { + let mut ids = cx.id_map.borrow_mut(); + write!( + w, + "
{}
", + Markdown( + &*dox, + &i.impl_item.links(cx), + &mut ids, + cx.shared.codes, + cx.shared.edition(), + &cx.shared.playground + ) + .into_string() + ); + } + } + if !impl_items.is_empty() { + w.write_str("
"); + w.push_buffer(impl_items); + close_tags.insert_str(0, "
"); + } w.write_str(&close_tags); } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt index c9ebffde039d8..9fca52451ed57 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.try_error_result.txt @@ -9,7 +9,7 @@ 9| | } 10| 6|} 11| | - 12| 1|fn main() -> Result<(),()> { + 12| 1|fn test1() -> Result<(),()> { 13| 1| let mut 14| 1| countdown = 10 15| | ; @@ -35,4 +35,91 @@ 34| | } 35| 0| Ok(()) 36| 1|} + 37| | + 38| |struct Thing1; + 39| |impl Thing1 { + 40| 18| fn get_thing_2(&self, return_error: bool) -> Result { + 41| 18| if return_error { + 42| 1| Err(()) + 43| | } else { + 44| 17| Ok(Thing2{}) + 45| | } + 46| 18| } + 47| |} + 48| | + 49| |struct Thing2; + 50| |impl Thing2 { + 51| 17| fn call(&self, return_error: bool) -> Result { + 52| 17| if return_error { + 53| 2| Err(()) + 54| | } else { + 55| 15| Ok(57) + 56| | } + 57| 17| } + 58| |} + 59| | + 60| 1|fn test2() -> Result<(),()> { + 61| 1| let thing1 = Thing1{}; + 62| 1| let mut + 63| 1| countdown = 10 + 64| | ; + 65| | for + 66| 6| _ + 67| | in + 68| 6| 0..10 + 69| | { + 70| 6| countdown + 71| 6| -= 1 + 72| 6| ; + 73| 6| if + 74| 6| countdown < 5 + 75| | { + 76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); + ^0 + 77| 1| thing1 + 78| 1| . + 79| 1| get_thing_2(/*return_error=*/ false) + 80| 0| ? + 81| | . + 82| 1| call(/*return_error=*/ true) + 83| 1| . + 84| 1| expect_err( + 85| 1| "call should fail" + 86| 1| ); + 87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; + ^0 ^0 ^0 + 88| 0| assert_eq!(val, 57); + 89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; + 90| 0| assert_eq!(val, 57); + 91| | } + 92| | else + 93| | { + 94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; + ^0 ^0 + 95| 5| assert_eq!(val, 57); + 96| 5| let val = thing1 + 97| 5| .get_thing_2(/*return_error=*/ false)? + ^0 + 98| 5| .call(/*return_error=*/ false)?; + ^0 + 99| 5| assert_eq!(val, 57); + 100| 5| let val = thing1 + 101| 5| .get_thing_2(/*return_error=*/ false) + 102| 0| ? + 103| 5| .call(/*return_error=*/ false) + 104| 0| ? + 105| | ; + 106| 5| assert_eq!(val, 57); + 107| | } + 108| | } + 109| 0| Ok(()) + 110| 1|} + 111| | + 112| 1|fn main() -> Result<(),()> { + 113| 1| test1().expect_err("test1 should fail"); + 114| 1| test2() + 115| 1| ? + 116| | ; + 117| 0| Ok(()) + 118| 1|} diff --git a/src/test/run-make-fulldeps/coverage/try_error_result.rs b/src/test/run-make-fulldeps/coverage/try_error_result.rs index 13c455172dd11..cd0acf7230222 100644 --- a/src/test/run-make-fulldeps/coverage/try_error_result.rs +++ b/src/test/run-make-fulldeps/coverage/try_error_result.rs @@ -9,7 +9,7 @@ fn call(return_error: bool) -> Result<(),()> { } } -fn main() -> Result<(),()> { +fn test1() -> Result<(),()> { let mut countdown = 10 ; @@ -34,3 +34,85 @@ fn main() -> Result<(),()> { } Ok(()) } + +struct Thing1; +impl Thing1 { + fn get_thing_2(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(Thing2{}) + } + } +} + +struct Thing2; +impl Thing2 { + fn call(&self, return_error: bool) -> Result { + if return_error { + Err(()) + } else { + Ok(57) + } + } +} + +fn test2() -> Result<(),()> { + let thing1 = Thing1{}; + let mut + countdown = 10 + ; + for + _ + in + 0..10 + { + countdown + -= 1 + ; + if + countdown < 5 + { + thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); + thing1 + . + get_thing_2(/*return_error=*/ false) + ? + . + call(/*return_error=*/ true) + . + expect_err( + "call should fail" + ); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; + assert_eq!(val, 57); + let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + } + else + { + let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false)? + .call(/*return_error=*/ false)?; + assert_eq!(val, 57); + let val = thing1 + .get_thing_2(/*return_error=*/ false) + ? + .call(/*return_error=*/ false) + ? + ; + assert_eq!(val, 57); + } + } + Ok(()) +} + +fn main() -> Result<(),()> { + test1().expect_err("test1 should fail"); + test2() + ? + ; + Ok(()) +} diff --git a/src/test/rustdoc/empty-impls.rs b/src/test/rustdoc/empty-impls.rs new file mode 100644 index 0000000000000..86dec32e6251c --- /dev/null +++ b/src/test/rustdoc/empty-impls.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] + +// @has foo/struct.Foo.html +// @has - '//div[@id="synthetic-implementations-list"]/h3[@id="impl-Send"]' 'impl Send for Foo' +pub struct Foo; + +pub trait EmptyTrait {} + +// @has - '//div[@id="trait-implementations-list"]/h3[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo' +impl EmptyTrait for Foo {} + +pub trait NotEmpty { + fn foo(&self); +} + +// @has - '//div[@id="trait-implementations-list"]/details/summary/h3[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo' +impl NotEmpty for Foo { + fn foo(&self) {} +} diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs index daebe059f8ef6..ddc14e68675a9 100644 --- a/src/test/rustdoc/issue-53812.rs +++ b/src/test/rustdoc/issue-53812.rs @@ -12,9 +12,9 @@ macro_rules! array_impls { } } -// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]/details[1]/summary/h3' 'MyStruct<[T; 0]>' -// @has - '//*[@id="implementors-list"]/details[2]/summary/h3' 'MyStruct<[T; 1]>' -// @has - '//*[@id="implementors-list"]/details[3]/summary/h3' 'MyStruct<[T; 2]>' -// @has - '//*[@id="implementors-list"]/details[4]/summary/h3' 'MyStruct<[T; 3]>' -// @has - '//*[@id="implementors-list"]/details[5]/summary/h3' 'MyStruct<[T; 10]>' +// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]/h3[1]' 'MyStruct<[T; 0]>' +// @has - '//*[@id="implementors-list"]/h3[2]' 'MyStruct<[T; 1]>' +// @has - '//*[@id="implementors-list"]/h3[3]' 'MyStruct<[T; 2]>' +// @has - '//*[@id="implementors-list"]/h3[4]' 'MyStruct<[T; 3]>' +// @has - '//*[@id="implementors-list"]/h3[5]' 'MyStruct<[T; 10]>' array_impls! { 10 3 2 1 0 } diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs index 2dbd1840dec55..6527eb4750455 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(generic_associated_types)] //~^ WARNING: the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] @@ -22,6 +20,7 @@ impl Foo for Fooer { } fn f(_arg : Box Foo = &'a ()>>) {} +//~^ the trait `Foo` cannot be made into an object fn main() { diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr index f3769827f04b2..49dfce8b4bd38 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -1,5 +1,5 @@ warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-in-trait-path.rs:3:12 + --> $DIR/gat-in-trait-path.rs:1:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -warning: 1 warning emitted +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:22:13 + | +LL | fn f(_arg : Box Foo = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | + = help: consider moving `A` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + +error: aborting due to previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs index ff38b3e93eb1a..6ee865072aebf 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.rs +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(generic_associated_types)] //~^ WARNING: the feature `generic_associated_types` is incomplete @@ -8,5 +6,6 @@ trait X { } fn _func1<'a>(_x: Box=&'a ()>>) {} +//~^ ERROR the trait `X` cannot be made into an object fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr index 0fbf704df76a1..65998afa7f914 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -1,5 +1,5 @@ warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-67510-pass.rs:3:12 + --> $DIR/issue-67510-pass.rs:1:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -warning: 1 warning emitted +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:8:19 + | +LL | fn _func1<'a>(_x: Box=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | + = help: consider moving `Y` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-67510-pass.rs:5:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + +error: aborting due to previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs index 5e73a88298622..9643c82db7732 100644 --- a/src/test/ui/generic-associated-types/issue-76535.rs +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -36,4 +36,6 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box> = Box::new(SuperStruct::new(0)); + //~^ ERROR the trait `SuperTrait` cannot be made into an object + //~^^ ERROR the trait `SuperTrait` cannot be made into an object } diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr index 17661e0d90a4a..d31560f12f0bb 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -23,6 +23,39 @@ help: use angle brackets to add missing lifetime argument LL | type SubType<'a><'a>: SubTrait; | ^^^^ -error: aborting due to previous error; 1 warning emitted +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:38:14 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | + = help: consider moving `SubType` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:7:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:38:57 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | + = help: consider moving `SubType` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:7:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = note: required because of the requirements on the impl of `CoerceUnsized>>>` for `Box` + = note: required by cast to type `Box>>` + +error: aborting due to 3 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs index 1b02aac8bcb24..4e47d3c665505 100644 --- a/src/test/ui/generic-associated-types/issue-78671.rs +++ b/src/test/ui/generic-associated-types/issue-78671.rs @@ -7,6 +7,7 @@ trait CollectionFamily { } fn floatify() { Box::new(Family) as &dyn CollectionFamily + //~^ the trait `CollectionFamily` cannot be made into an object } struct Family; diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr index 7a9aced5beab8..c9febfb59af62 100644 --- a/src/test/ui/generic-associated-types/issue-78671.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.stderr @@ -14,6 +14,22 @@ help: use angle brackets to add missing type argument LL | type Member; | ^^^ -error: aborting due to previous error +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:9:25 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | + = help: consider moving `Member` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-78671.rs:5:10 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member; + | ^^^^^^ ...because it contains the generic associated type `Member` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs index aeb33ca54641c..b2ba3c24abbe1 100644 --- a/src/test/ui/generic-associated-types/issue-79422.rs +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -42,5 +42,6 @@ impl MapLike for Source { fn main() { let m = Box::new(std::collections::BTreeMap::::new()) as Box>>; - //~^^ ERROR type mismatch resolving + //~^^ the trait `MapLike` cannot be made into an object + //~^^ the trait `MapLike` cannot be made into an object } diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr index a119bff03e290..4973ae19729ac 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -14,17 +14,39 @@ help: use angle brackets to add missing lifetime argument LL | type VRefCont<'a><'a>: RefCont<'a, V>; | ^^^^ -error[E0271]: type mismatch resolving ` as MapLike>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)` +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:44:12 + | +LL | as Box>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | + = help: consider moving `VRefCont` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:21:10 + | +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V>; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + +error[E0038]: the trait `MapLike` cannot be made into an object --> $DIR/issue-79422.rs:43:13 | LL | let m = Box::new(std::collections::BTreeMap::::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | + = help: consider moving `VRefCont` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:21:10 | - = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` - found reference `&'static u8` - = note: required for the cast to the object type `dyn MapLike + 'static)>` +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V>; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = note: required because of the requirements on the impl of `CoerceUnsized + 'static)>>>` for `Box>` + = note: required by cast to type `Box + 'static)>>` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0271. -For more information about an error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs new file mode 100644 index 0000000000000..997a550b0effb --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.rs @@ -0,0 +1,16 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait StreamingIterator { + type Item<'a> where Self: 'a; + fn size_hint(&self) -> (usize, Option); + // Uncommenting makes `StreamingIterator` not object safe +// fn next(&mut self) -> Self::Item<'_>; +} + +fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + //~^ the trait `StreamingIterator` cannot be made into an object + x.size_hint().0 +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr new file mode 100644 index 0000000000000..a8f1768ba2617 --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:11:16 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | + = help: consider moving `Item` to another trait +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/trait-objects.rs:5:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`.