diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 33f75437478b5..cbb1c307354f3 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1065,7 +1065,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { )?; ocx.infcx.add_item_bounds_for_hidden_type( - opaque_type_key, + opaque_type_key.def_id.to_def_id(), + opaque_type_key.substs, cause, param_env, hidden_ty.ty, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 49ee276af4e6f..fcc68010a34c6 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -3,7 +3,7 @@ use crate::errors; /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, attr}; +use rustc_ast::{self as ast, attr, GenericParamKind}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_expand::base::*; @@ -122,11 +122,7 @@ pub fn expand_test_or_bench( let ast::ItemKind::Fn(fn_) = &item.kind else { not_testable_error(cx, attr_sp, Some(&item)); return if is_stmt { - vec![Annotatable::Stmt(P(ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: item.span, - kind: ast::StmtKind::Item(item), - }))] + vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] } else { vec![Annotatable::Item(item)] }; @@ -138,7 +134,11 @@ pub fn expand_test_or_bench( if (!is_bench && !has_test_signature(cx, &item)) || (is_bench && !has_bench_signature(cx, &item)) { - return vec![Annotatable::Item(item)]; + return if is_stmt { + vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] + } else { + vec![Annotatable::Item(item)] + }; } let sp = cx.with_def_site_ctxt(item.span); @@ -550,24 +550,21 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { return false; } - match (has_output, has_should_panic_attr) { - (true, true) => { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - false - } - (true, false) => { - if !generics.params.is_empty() { - sd.span_err( - i.span, - "functions used as tests must have signature fn() -> ()", - ); - false - } else { - true - } - } - (false, _) => true, + if has_should_panic_attr && has_output { + sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); + return false; + } + + if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) + { + sd.span_err( + i.span, + "functions used as tests can not have any non-lifetime generic parameters", + ); + return false; } + + true } _ => { // should be unreachable because `is_test_fn_item` should catch all non-fn items diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 6b8293f90f10a..b19f685a4a455 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -536,7 +536,8 @@ impl<'tcx> InferCtxt<'tcx> { )?; self.add_item_bounds_for_hidden_type( - opaque_type_key, + opaque_type_key.def_id.to_def_id(), + opaque_type_key.substs, cause, param_env, hidden_ty, @@ -598,7 +599,8 @@ impl<'tcx> InferCtxt<'tcx> { pub fn add_item_bounds_for_hidden_type( &self, - OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, + def_id: DefId, + substs: ty::SubstsRef<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, @@ -631,7 +633,7 @@ impl<'tcx> InferCtxt<'tcx> { // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. }) - if def_id.to_def_id() == def_id2 && substs == substs2 => + if def_id == def_id2 && substs == substs2 => { hidden_ty } @@ -640,7 +642,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::Alias( ty::Projection, ty::AliasTy { def_id: def_id2, substs: substs2, .. }, - ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty, + ) if def_id == def_id2 && substs == substs2 => hidden_ty, _ => ty, }, lt_op: |lt| lt, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 8625958ff5a2c..ff9ce98d5a407 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -750,13 +750,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { pub(super) fn add_item_bounds_for_hidden_type( &mut self, - opaque_type_key: OpaqueTypeKey<'tcx>, + opaque_def_id: DefId, + opaque_substs: ty::SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, ) { let mut obligations = Vec::new(); self.infcx.add_item_bounds_for_hidden_type( - opaque_type_key, + opaque_def_id, + opaque_substs, ObligationCause::dummy(), param_env, hidden_ty, @@ -786,7 +788,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ecx.eq(param_env, a, b)?; } ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type(candidate_key, param_env, candidate_ty); + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.to_def_id(), + candidate_key.substs, + param_env, + candidate_ty, + ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) })); } diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs index 538c16c8ce2cd..16194f5ad69c0 100644 --- a/compiler/rustc_trait_selection/src/solve/opaques.rs +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -20,8 +20,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else { return Err(NoSolution); }; - let opaque_ty = - ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs }; // FIXME: at some point we should call queries without defining // new opaque types but having the existing opaque type definitions. // This will require moving this below "Prefer opaques registered already". @@ -41,7 +39,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Ok(()) => {} } // Prefer opaques registered already. - let matches = self.unify_existing_opaque_tys(goal.param_env, opaque_ty, expected); + let opaque_type_key = + ty::OpaqueTypeKey { def_id: opaque_ty_def_id, substs: opaque_ty.substs }; + let matches = + self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected); if !matches.is_empty() { if let Some(response) = self.try_merge_responses(&matches) { return Ok(response); @@ -50,11 +51,24 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } // Otherwise, define a new opaque type - self.insert_hidden_type(opaque_ty, goal.param_env, expected)?; - self.add_item_bounds_for_hidden_type(opaque_ty, goal.param_env, expected); + self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?; + self.add_item_bounds_for_hidden_type( + opaque_ty.def_id, + opaque_ty.substs, + goal.param_env, + expected, + ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (Reveal::UserFacing, SolverMode::Coherence) => { + // An impossible opaque type bound is the only way this goal will fail + // e.g. assigning `impl Copy := NotCopy` + self.add_item_bounds_for_hidden_type( + opaque_ty.def_id, + opaque_ty.substs, + goal.param_env, + expected, + ); self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } (Reveal::All, _) => { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 2d97a80822581..1b6e92946c4be 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -322,8 +322,12 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> }; // `tcx.normalize_projection_ty` may normalize to a type that still has // unevaluated consts, so keep normalizing here if that's the case. - if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { - res.try_super_fold_with(self)? + // Similarly, `tcx.normalize_weak_ty` will only unwrap one layer of type + // and we need to continue folding it to reveal the TAIT behind it. + if res != ty + && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Weak) + { + res.try_fold_with(self)? } else { res } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f2dfa6921f41c..9f209b4b62326 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -417,17 +417,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Fast path to avoid evaluating an obligation that trivially holds. // There may be more bounds, but these are checked by the regular path. ty::FnPtr(..) => return false, + // These may potentially implement `FnPtr` ty::Placeholder(..) | ty::Dynamic(_, _, _) | ty::Alias(_, _) | ty::Infer(_) - | ty::Param(..) => {} + | ty::Param(..) + | ty::Bound(_, _) => {} - ty::Bound(_, _) => span_bug!( - obligation.cause.span(), - "cannot have escaping bound var in self type of {obligation:#?}" - ), // These can't possibly implement `FnPtr` as they are concrete types // and not `FnPtr` ty::Bool diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs index 90cb797391a08..d27a9dfc176e3 100644 --- a/library/core/src/future/poll_fn.rs +++ b/library/core/src/future/poll_fn.rs @@ -24,6 +24,93 @@ use crate::task::{Context, Poll}; /// assert_eq!(read_future.await, "Hello, World!".to_owned()); /// # } /// ``` +/// +/// ## Capturing a pinned state +/// +/// Example of a closure wrapping inner futures: +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select( +/// a: impl Future, +/// b: impl Future, +/// ) -> impl Future +/// { +/// let (mut a, mut b) = (Box::pin(a), Box::pin(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }) +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// +/// let a = future::pending(); +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 27); +/// +/// let a = async { 42 }; +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); // biased towards `a` in case of tie! +/// # } +/// ``` +/// +/// This time without [`Box::pin`]ning: +/// +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::pin::pin; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select( +/// a: impl Future, +/// b: impl Future, +/// ) -> impl Future +/// { +/// async { +/// let (mut a, mut b) = (pin!(a), pin!(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }).await +/// } +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// # } +/// ``` +/// +/// - Notice how, by virtue of being in an `async` context, we have been able to make the [`pin!`] +/// macro work, thereby avoiding any need for the `unsafe` +/// [Pin::new_unchecked](&mut fut) constructor. +/// +/// [`pin!`]: crate::pin::pin! #[stable(feature = "future_poll_fn", since = "1.64.0")] pub fn poll_fn(f: F) -> PollFn where diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 954d88d548e82..c51913fa8ab8d 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1770,14 +1770,8 @@ impl fmt::Display for Ipv6Addr { f.write_str("::") } else if self.is_loopback() { f.write_str("::1") - } else if let Some(ipv4) = self.to_ipv4() { - match segments[5] { - // IPv4 Compatible address - 0 => write!(f, "::{}", ipv4), - // IPv4 Mapped address - 0xffff => write!(f, "::ffff:{}", ipv4), - _ => unreachable!(), - } + } else if let Some(ipv4) = self.to_ipv4_mapped() { + write!(f, "::ffff:{}", ipv4) } else { #[derive(Copy, Clone, Default)] struct Span { diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 5a6ac08c08815..7530fc084874d 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -139,7 +139,7 @@ fn ipv6_addr_to_string() { // ipv4-compatible address let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280); - assert_eq!(a1.to_string(), "::192.0.2.128"); + assert_eq!(a1.to_string(), "::c000:280"); // v6 address with no zero segments assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f"); @@ -316,7 +316,7 @@ fn ip_properties() { check!("::", unspec); check!("::1", loopback); - check!("::0.0.0.2", global); + check!("::2", global); check!("1::", global); check!("fc00::"); check!("fdff:ffff::"); @@ -607,7 +607,7 @@ fn ipv6_properties() { check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback); - check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); + check!("::2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs index 68c7cd94d322f..35a69cead4826 100644 --- a/library/core/tests/net/socket_addr.rs +++ b/library/core/tests/net/socket_addr.rs @@ -34,7 +34,7 @@ fn ipv6_socket_addr_to_string() { // IPv4-compatible address. assert_eq!( SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(), - "[::192.0.2.128]:8080" + "[::c000:280]:8080" ); // IPv6 address with no zero segments. diff --git a/library/std/src/net/socket_addr/tests.rs b/library/std/src/net/socket_addr/tests.rs index dfc6dabbed1ed..6a065cfba2105 100644 --- a/library/std/src/net/socket_addr/tests.rs +++ b/library/std/src/net/socket_addr/tests.rs @@ -85,7 +85,7 @@ fn ipv6_socket_addr_to_string() { // IPv4-compatible address. assert_eq!( SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(), - "[::192.0.2.128]:8080" + "[::c000:280]:8080" ); // IPv6 address with no zero segments. diff --git a/src/ci/github-actions/problem_matchers.json b/src/ci/github-actions/problem_matchers.json index 37561924b7d4f..333dea1509bdd 100644 --- a/src/ci/github-actions/problem_matchers.json +++ b/src/ci/github-actions/problem_matchers.json @@ -10,6 +10,46 @@ "message": 3 } ] + }, + { + "owner": "cargo-common", + "pattern": [ + { + "regexp": "^(warning|warn|error)(\\[(\\S*)\\])?: (.*)$", + "severity": 1, + "message": 4, + "code": 3 + }, + { + "regexp": "^\\s+-->\\s(\\S+):(\\d+):(\\d+)$", + "file": 1, + "line": 2, + "column": 3 + } + ] + }, + { + "owner": "cargo-test", + "pattern": [ + { + "regexp": "^.*panicked\\s+at\\s+'(.*)',\\s+(.*):(\\d+):(\\d+)$", + "message": 1, + "file": 2, + "line": 3, + "column": 4 + } + ] + }, + { + "owner": "cargo-fmt", + "pattern": [ + { + "regexp": "^(Diff in (\\S+)) at line (\\d+):", + "message": 1, + "file": 2, + "line": 3 + } + ] } ] } diff --git a/tests/ui/test-attrs/test-function-signature.rs b/tests/ui/test-attrs/test-function-signature.rs new file mode 100644 index 0000000000000..9e86e9209e320 --- /dev/null +++ b/tests/ui/test-attrs/test-function-signature.rs @@ -0,0 +1,31 @@ +// compile-flags: --test + +#[test] +fn foo() -> Result<(), ()> { + Ok(()) +} + +#[test] +fn bar() -> i32 { //~ ERROR the trait bound `i32: Termination` is not satisfied + 0 +} + +#[test] +fn baz(val: i32) {} //~ ERROR functions used as tests can not have any arguments + +#[test] +fn lifetime_generic<'a>() -> Result<(), &'a str> { + Err("coerce me to any lifetime") +} + +#[test] +fn type_generic() {} //~ ERROR functions used as tests can not have any non-lifetime generic parameters + +#[test] +fn const_generic() {} //~ ERROR functions used as tests can not have any non-lifetime generic parameters + +// Regression test for . This used to ICE. +fn nested() { + #[test] + fn foo(arg: ()) {} //~ ERROR functions used as tests can not have any arguments +} diff --git a/tests/ui/test-attrs/test-function-signature.stderr b/tests/ui/test-attrs/test-function-signature.stderr new file mode 100644 index 0000000000000..abdb30dc9312b --- /dev/null +++ b/tests/ui/test-attrs/test-function-signature.stderr @@ -0,0 +1,39 @@ +error: functions used as tests can not have any arguments + --> $DIR/test-function-signature.rs:14:1 + | +LL | fn baz(val: i32) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: functions used as tests can not have any non-lifetime generic parameters + --> $DIR/test-function-signature.rs:22:1 + | +LL | fn type_generic() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions used as tests can not have any non-lifetime generic parameters + --> $DIR/test-function-signature.rs:25:1 + | +LL | fn const_generic() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions used as tests can not have any arguments + --> $DIR/test-function-signature.rs:30:5 + | +LL | fn foo(arg: ()) {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `i32: Termination` is not satisfied + --> $DIR/test-function-signature.rs:9:13 + | +LL | #[test] + | ------- in this procedural macro expansion +LL | fn bar() -> i32 { + | ^^^ the trait `Termination` is not implemented for `i32` + | +note: required by a bound in `assert_test_result` + --> $SRC_DIR/test/src/lib.rs:LL:COL + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs new file mode 100644 index 0000000000000..96a7424f0dc9c --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs @@ -0,0 +1,12 @@ +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +fn auto_trait() +where + for T: PartialEq + PartialOrd, +{} + +fn main() { + auto_trait(); + //~^ ERROR can't compare `T` with `T` +} diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr new file mode 100644 index 0000000000000..da09343fb276b --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -0,0 +1,28 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/foreach-partial-eq.rs:1:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `T` with `T` + --> $DIR/foreach-partial-eq.rs:10:5 + | +LL | auto_trait(); + | ^^^^^^^^^^ no implementation for `T < T` and `T > T` + | + = help: the trait `PartialOrd` is not implemented for `T` +note: required by a bound in `auto_trait` + --> $DIR/foreach-partial-eq.rs:6:27 + | +LL | fn auto_trait() + | ---------- required by a bound in this function +LL | where +LL | for T: PartialEq + PartialOrd, + | ^^^^^^^^^^ required by this bound in `auto_trait` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs new file mode 100644 index 0000000000000..44158349fdd64 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs @@ -0,0 +1,12 @@ +// compile-flags: --crate-type=lib -Cdebuginfo=2 +// build-pass + +#![feature(type_alias_impl_trait)] + +type Debuggable = impl core::fmt::Debug; + +static mut TEST: Option = None; + +fn foo() -> Debuggable { + 0u32 +} diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs index b97e444c6d0e0..386b77d4d1618 100644 --- a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs +++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -1,6 +1,8 @@ // Regression test for issue #76202 // Tests that we don't ICE when we have a trait impl on a TAIT. +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next // check-pass #![feature(type_alias_impl_trait)]