Skip to content

Commit e70c60d

Browse files
committed
Auto merge of rust-lang#97783 - matthiaskrgr:rollup-14t9htt, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#90905 (Add empty impl blocks if they have documentation) - rust-lang#97683 (Fail gracefully when encountering an HRTB in APIT. ) - rust-lang#97721 (Do `suggest_await_before_try` with infer variables in self, and clean up binders) - rust-lang#97752 (typo: `-Zcodegen-backend=llvm -Cpasses=list` should work now) - rust-lang#97759 (Suggest adding `{}` for `'label: non_block_expr`) - rust-lang#97764 (use strict provenance APIs) - rust-lang#97765 (Restore a test that was intended to test `as` cast to ptr) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6609c67 + 1258fa9 commit e70c60d

File tree

23 files changed

+419
-82
lines changed

23 files changed

+419
-82
lines changed

compiler/rustc_driver/src/lib.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1055,13 +1055,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
10551055
}
10561056

10571057
if cg_flags.iter().any(|x| *x == "passes=list") {
1058-
let backend_name = debug_flags.iter().find_map(|x| {
1059-
if x.starts_with("codegen-backend=") {
1060-
Some(&x["codegen-backends=".len()..])
1061-
} else {
1062-
None
1063-
}
1064-
});
1058+
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
10651059
get_codegen_backend(&None, backend_name).print_passes();
10661060
return None;
10671061
}

compiler/rustc_hir/src/hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ impl<'hir> WherePredicate<'hir> {
734734
}
735735
}
736736

737-
#[derive(Debug, HashStable_Generic, PartialEq, Eq)]
737+
#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
738738
pub enum PredicateOrigin {
739739
WhereClause,
740740
GenericParam,

compiler/rustc_parse/src/parser/expr.rs

+62-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ use rustc_ast::tokenstream::Spacing;
1313
use rustc_ast::util::classify;
1414
use rustc_ast::util::literal::LitError;
1515
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
16+
use rustc_ast::visit::Visitor;
17+
use rustc_ast::StmtKind;
1618
use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp, DUMMY_NODE_ID};
1719
use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
1820
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
1921
use rustc_ast_pretty::pprust;
22+
use rustc_data_structures::thin_vec::ThinVec;
2023
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
2124
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
2225
use rustc_session::lint::BuiltinLintDiagnostics;
@@ -1548,9 +1551,66 @@ impl<'a> Parser<'a> {
15481551
Ok(self.mk_expr_err(lo))
15491552
} else {
15501553
let msg = "expected `while`, `for`, `loop` or `{` after a label";
1551-
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
1554+
1555+
let mut err = self.struct_span_err(self.token.span, msg);
1556+
err.span_label(self.token.span, msg);
1557+
15521558
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
1553-
self.parse_expr()
1559+
let expr = self.parse_expr().map(|expr| {
1560+
let span = expr.span;
1561+
1562+
let found_labeled_breaks = {
1563+
struct FindLabeledBreaksVisitor(bool);
1564+
1565+
impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
1566+
fn visit_expr_post(&mut self, ex: &'ast Expr) {
1567+
if let ExprKind::Break(Some(_label), _) = ex.kind {
1568+
self.0 = true;
1569+
}
1570+
}
1571+
}
1572+
1573+
let mut vis = FindLabeledBreaksVisitor(false);
1574+
vis.visit_expr(&expr);
1575+
vis.0
1576+
};
1577+
1578+
// Suggestion involves adding a (as of time of writing this, unstable) labeled block.
1579+
//
1580+
// If there are no breaks that may use this label, suggest removing the label and
1581+
// recover to the unmodified expression.
1582+
if !found_labeled_breaks {
1583+
let msg = "consider removing the label";
1584+
err.span_suggestion_verbose(
1585+
lo.until(span),
1586+
msg,
1587+
"",
1588+
Applicability::MachineApplicable,
1589+
);
1590+
1591+
return expr;
1592+
}
1593+
1594+
let sugg_msg = "consider enclosing expression in a block";
1595+
let suggestions = vec![
1596+
(span.shrink_to_lo(), "{ ".to_owned()),
1597+
(span.shrink_to_hi(), " }".to_owned()),
1598+
];
1599+
1600+
err.multipart_suggestion_verbose(
1601+
sugg_msg,
1602+
suggestions,
1603+
Applicability::MachineApplicable,
1604+
);
1605+
1606+
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`.
1607+
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
1608+
let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span);
1609+
self.mk_expr(span, ExprKind::Block(blk, label), ThinVec::new())
1610+
});
1611+
1612+
err.emit();
1613+
expr
15541614
}?;
15551615

15561616
if !ate_colon && consume_colon {

compiler/rustc_resolve/src/late/lifetimes.rs

+64-7
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ enum Scope<'a> {
207207
/// In some cases not allowing late bounds allows us to avoid ICEs.
208208
/// This is almost ways set to true.
209209
allow_late_bound: bool,
210+
211+
/// If this binder comes from a where clause, specify how it was created.
212+
/// This is used to diagnose inaccessible lifetimes in APIT:
213+
/// ```ignore (illustrative)
214+
/// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
215+
/// ```
216+
where_bound_origin: Option<hir::PredicateOrigin>,
210217
},
211218

212219
/// Lifetimes introduced by a fn are scoped to the call-site for that fn,
@@ -277,17 +284,19 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
277284
opaque_type_parent,
278285
scope_type,
279286
hir_id,
280-
s: _,
281287
allow_late_bound,
288+
where_bound_origin,
289+
s: _,
282290
} => f
283291
.debug_struct("Binder")
284292
.field("lifetimes", lifetimes)
285293
.field("next_early_index", next_early_index)
286294
.field("opaque_type_parent", opaque_type_parent)
287295
.field("scope_type", scope_type)
288296
.field("hir_id", hir_id)
289-
.field("s", &"..")
290297
.field("allow_late_bound", allow_late_bound)
298+
.field("where_bound_origin", where_bound_origin)
299+
.field("s", &"..")
291300
.finish(),
292301
Scope::Body { id, s: _ } => {
293302
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
@@ -638,6 +647,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
638647
opaque_type_parent: false,
639648
scope_type: BinderScopeType::Normal,
640649
allow_late_bound: true,
650+
where_bound_origin: None,
641651
};
642652
self.with(scope, move |this| intravisit::walk_fn(this, fk, fd, b, s, hir_id));
643653
}
@@ -753,6 +763,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
753763
scope_type: BinderScopeType::Normal,
754764
s: ROOT_SCOPE,
755765
allow_late_bound: false,
766+
where_bound_origin: None,
756767
};
757768
self.with(scope, |this| {
758769
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -818,6 +829,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
818829
opaque_type_parent: false,
819830
scope_type: BinderScopeType::Normal,
820831
allow_late_bound: true,
832+
where_bound_origin: None,
821833
};
822834
self.with(scope, |this| {
823835
// a bare fn has no bounds, so everything
@@ -1006,6 +1018,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10061018
opaque_type_parent: false,
10071019
scope_type: BinderScopeType::Normal,
10081020
allow_late_bound: false,
1021+
where_bound_origin: None,
10091022
};
10101023
this.with(scope, |this| {
10111024
this.visit_generics(generics);
@@ -1026,6 +1039,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10261039
opaque_type_parent: false,
10271040
scope_type: BinderScopeType::Normal,
10281041
allow_late_bound: false,
1042+
where_bound_origin: None,
10291043
};
10301044
self.with(scope, |this| {
10311045
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -1084,6 +1098,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10841098
opaque_type_parent: true,
10851099
scope_type: BinderScopeType::Normal,
10861100
allow_late_bound: false,
1101+
where_bound_origin: None,
10871102
};
10881103
self.with(scope, |this| {
10891104
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -1151,6 +1166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
11511166
opaque_type_parent: true,
11521167
scope_type: BinderScopeType::Normal,
11531168
allow_late_bound: true,
1169+
where_bound_origin: None,
11541170
};
11551171
self.with(scope, |this| {
11561172
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -1266,6 +1282,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
12661282
ref bounded_ty,
12671283
bounds,
12681284
ref bound_generic_params,
1285+
origin,
12691286
..
12701287
}) => {
12711288
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
@@ -1296,6 +1313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
12961313
opaque_type_parent: false,
12971314
scope_type: BinderScopeType::Normal,
12981315
allow_late_bound: true,
1316+
where_bound_origin: Some(origin),
12991317
};
13001318
this.with(scope, |this| {
13011319
this.visit_ty(&bounded_ty);
@@ -1368,6 +1386,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
13681386
opaque_type_parent: false,
13691387
scope_type,
13701388
allow_late_bound: true,
1389+
where_bound_origin: None,
13711390
};
13721391
self.with(scope, |this| {
13731392
intravisit::walk_param_bound(this, bound);
@@ -1420,6 +1439,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
14201439
opaque_type_parent: false,
14211440
scope_type,
14221441
allow_late_bound: true,
1442+
where_bound_origin: None,
14231443
};
14241444
self.with(scope, |this| {
14251445
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
@@ -1680,6 +1700,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
16801700
opaque_type_parent: true,
16811701
scope_type: BinderScopeType::Normal,
16821702
allow_late_bound: true,
1703+
where_bound_origin: None,
16831704
};
16841705
self.with(scope, walk);
16851706
}
@@ -1783,12 +1804,48 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
17831804
}
17841805

17851806
self.insert_lifetime(lifetime_ref, def);
1786-
} else {
1787-
self.tcx.sess.delay_span_bug(
1788-
lifetime_ref.span,
1789-
&format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1790-
);
1807+
return;
17911808
}
1809+
1810+
// We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
1811+
// AST-based resolution does not care for impl-trait desugaring, which are the
1812+
// responibility of lowering. This may create a mismatch between the resolution
1813+
// AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1814+
// ```
1815+
// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1816+
// ```
1817+
//
1818+
// In such case, walk back the binders to diagnose it properly.
1819+
let mut scope = self.scope;
1820+
loop {
1821+
match *scope {
1822+
Scope::Binder {
1823+
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1824+
} => {
1825+
let mut err = self.tcx.sess.struct_span_err(
1826+
lifetime_ref.span,
1827+
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
1828+
);
1829+
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1830+
err.emit();
1831+
return;
1832+
}
1833+
Scope::Root => break,
1834+
Scope::Binder { s, .. }
1835+
| Scope::Body { s, .. }
1836+
| Scope::Elision { s, .. }
1837+
| Scope::ObjectLifetimeDefault { s, .. }
1838+
| Scope::Supertrait { s, .. }
1839+
| Scope::TraitRefBoundary { s, .. } => {
1840+
scope = s;
1841+
}
1842+
}
1843+
}
1844+
1845+
self.tcx.sess.delay_span_bug(
1846+
lifetime_ref.span,
1847+
&format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1848+
);
17921849
}
17931850

17941851
fn visit_segment_args(

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+18-30
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::{
55

66
use crate::autoderef::Autoderef;
77
use crate::infer::InferCtxt;
8-
use crate::traits::normalize_projection_type;
8+
use crate::traits::normalize_to;
99

1010
use rustc_data_structures::fx::FxHashSet;
1111
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -2706,55 +2706,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
27062706
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
27072707

27082708
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
2709-
2710-
// Do not check on infer_types to avoid panic in evaluate_obligation.
2711-
if self_ty.has_infer_types() {
2712-
return;
2713-
}
2714-
let self_ty = self.tcx.erase_regions(self_ty);
2715-
27162709
let impls_future = self.type_implements_trait(
27172710
future_trait,
2718-
self_ty.skip_binder(),
2711+
self.tcx.erase_late_bound_regions(self_ty),
27192712
ty::List::empty(),
27202713
obligation.param_env,
27212714
);
2715+
if !impls_future.must_apply_modulo_regions() {
2716+
return;
2717+
}
27222718

27232719
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
27242720
// `<T as Future>::Output`
2725-
let projection_ty = ty::ProjectionTy {
2726-
// `T`
2727-
substs: self.tcx.mk_substs_trait(
2728-
trait_pred.self_ty().skip_binder(),
2729-
&self.fresh_substs_for_item(span, item_def_id)[1..],
2730-
),
2731-
// `Future::Output`
2732-
item_def_id,
2733-
};
2734-
2735-
let mut selcx = SelectionContext::new(self);
2736-
2737-
let mut obligations = vec![];
2738-
let normalized_ty = normalize_projection_type(
2739-
&mut selcx,
2721+
let projection_ty = trait_pred.map_bound(|trait_pred| {
2722+
self.tcx.mk_projection(
2723+
item_def_id,
2724+
// Future::Output has no substs
2725+
self.tcx.mk_substs_trait(trait_pred.self_ty(), &[]),
2726+
)
2727+
});
2728+
let projection_ty = normalize_to(
2729+
&mut SelectionContext::new(self),
27402730
obligation.param_env,
2741-
projection_ty,
27422731
obligation.cause.clone(),
2743-
0,
2744-
&mut obligations,
2732+
projection_ty,
2733+
&mut vec![],
27452734
);
27462735

27472736
debug!(
27482737
"suggest_await_before_try: normalized_projection_type {:?}",
2749-
self.resolve_vars_if_possible(normalized_ty)
2738+
self.resolve_vars_if_possible(projection_ty)
27502739
);
27512740
let try_obligation = self.mk_trait_obligation_with_new_self_ty(
27522741
obligation.param_env,
2753-
trait_pred.map_bound(|trait_pred| (trait_pred, normalized_ty.ty().unwrap())),
2742+
trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
27542743
);
27552744
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
27562745
if self.predicate_may_hold(&try_obligation)
2757-
&& impls_future.must_apply_modulo_regions()
27582746
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
27592747
&& snippet.ends_with('?')
27602748
{

library/core/src/ptr/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ pub const fn null<T>() -> *const T {
532532
#[rustc_diagnostic_item = "ptr_null"]
533533
#[cfg(not(bootstrap))]
534534
pub const fn null<T: ?Sized + Thin>() -> *const T {
535-
from_raw_parts(0 as *const (), ())
535+
from_raw_parts(invalid(0), ())
536536
}
537537

538538
/// Creates a null mutable raw pointer.
@@ -709,7 +709,7 @@ where
709709
#[rustc_diagnostic_item = "ptr_null_mut"]
710710
#[cfg(not(bootstrap))]
711711
pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
712-
from_raw_parts_mut(0 as *mut (), ())
712+
from_raw_parts_mut(invalid_mut(0), ())
713713
}
714714

715715
/// Forms a raw slice from a pointer and a length.

0 commit comments

Comments
 (0)