Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #112789

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4bf0061
Fix ICE for nested test function with arguments.
Jun 6, 2023
774f782
Deny non-lifetime generics for test functions.
Jun 6, 2023
5049743
Add test for test function signature verification.
Jun 6, 2023
3a9a8d4
Alter `Display` for `Ipv6Addr` for IPv4-compatible addresses
clarfonthey Jun 14, 2023
2f2c3f5
Fix `Ipv6Addr: Display` tests
clarfonthey Jun 14, 2023
2dce58d
Fix `SocketAddrV6: Display` tests
clarfonthey Jun 14, 2023
94f7a79
[doc] poll_fn: explain how to pin captured state safely
danielhenrymantilla Apr 5, 2023
493b18b
Continue folding in query normalizer on weak aliases
compiler-errors Jun 18, 2023
48ad6e3
Don't consider TAIT normalizable to hidden ty if it would result in i…
compiler-errors Jun 18, 2023
29c74d5
Don't ICE on bound var in reject_fn_ptr_impls
compiler-errors Jun 19, 2023
7c7cc12
Add gha problem matcher
oli-obk Jun 19, 2023
29ddde6
Rollup merge of #109970 - danielhenrymantilla:add-poll-fn-pin-clarifi…
jyn514 Jun 19, 2023
0413f32
Rollup merge of #112366 - lukas-code:test, r=Nilstrieb
jyn514 Jun 19, 2023
6bf51c8
Rollup merge of #112606 - clarfonthey:ip-display, r=thomcc
jyn514 Jun 19, 2023
7fe7a98
Rollup merge of #112777 - compiler-errors:normalize-weak-more, r=oli-obk
jyn514 Jun 19, 2023
bc61d6f
Rollup merge of #112781 - compiler-errors:new-solver-tait-overlaps-hi…
jyn514 Jun 19, 2023
0a4cfe5
Rollup merge of #112783 - compiler-errors:nlb-fnptr-reject-ice, r=fee…
jyn514 Jun 19, 2023
8b226e1
Rollup merge of #112787 - oli-obk:gha_tinder_for_problems, r=jyn514
jyn514 Jun 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
45 changes: 21 additions & 24 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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)]
};
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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
}
Expand All @@ -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,
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}));
}
Expand Down
24 changes: 19 additions & 5 deletions compiler/rustc_trait_selection/src/solve/opaques.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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".
Expand All @@ -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);
Expand All @@ -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, _) => {
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> 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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
87 changes: 87 additions & 0 deletions library/core/src/future/poll_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(
/// a: impl Future<Output = T>,
/// b: impl Future<Output = T>,
/// ) -> impl Future<Output = T>
/// {
/// 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<T>(
/// a: impl Future<Output = T>,
/// b: impl Future<Output = T>,
/// ) -> impl Future<Output = T>
/// {
/// 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`
/// <code>[Pin::new_unchecked](&mut fut)</code> constructor.
///
/// [`pin!`]: crate::pin::pin!
#[stable(feature = "future_poll_fn", since = "1.64.0")]
pub fn poll_fn<T, F>(f: F) -> PollFn<F>
where
Expand Down
10 changes: 2 additions & 8 deletions library/core/src/net/ip_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions library/core/tests/net/ip_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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::");
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion library/core/tests/net/socket_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/net/socket_addr/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading