Skip to content

Commit 69eb996

Browse files
committed
Auto merge of rust-lang#89417 - Manishearth:rollup-j2gdu95, r=Manishearth
Rollup of 7 pull requests Successful merges: - rust-lang#88838 (Do not suggest importing inaccessible items) - rust-lang#89251 (Detect when negative literal indices are used and suggest appropriate code) - rust-lang#89321 (Rebase resume argument projections during state transform) - rust-lang#89327 (Pick one possible lifetime in case there are multiple choices) - rust-lang#89344 (Cleanup lower_generics_mut and make span be the bound itself) - rust-lang#89397 (Update `llvm` submodule to fix function name mangling on x86 Windows) - rust-lang#89412 (Add regression test for issues rust-lang#88969 and rust-lang#89119 ) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 4e4942d + 4571fea commit 69eb996

28 files changed

+560
-160
lines changed

compiler/rustc_ast_lowering/src/item.rs

+38-25
Original file line numberDiff line numberDiff line change
@@ -1328,32 +1328,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
13281328
// keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
13291329
// where clauses for `?Sized`.
13301330
for pred in &generics.where_clause.predicates {
1331-
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
1332-
'next_bound: for bound in &bound_pred.bounds {
1333-
if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
1334-
// Check if the where clause type is a plain type parameter.
1335-
match self
1336-
.resolver
1337-
.get_partial_res(bound_pred.bounded_ty.id)
1338-
.map(|d| (d.base_res(), d.unresolved_segments()))
1339-
{
1340-
Some((Res::Def(DefKind::TyParam, def_id), 0))
1341-
if bound_pred.bound_generic_params.is_empty() =>
1342-
{
1343-
for param in &generics.params {
1344-
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
1345-
continue 'next_bound;
1346-
}
1347-
}
1348-
}
1349-
_ => {}
1350-
}
1351-
self.diagnostic().span_err(
1352-
bound_pred.bounded_ty.span,
1353-
"`?Trait` bounds are only permitted at the \
1354-
point where a type parameter is declared",
1355-
);
1331+
let bound_pred = match *pred {
1332+
WherePredicate::BoundPredicate(ref bound_pred) => bound_pred,
1333+
_ => continue,
1334+
};
1335+
let compute_is_param = || {
1336+
// Check if the where clause type is a plain type parameter.
1337+
match self
1338+
.resolver
1339+
.get_partial_res(bound_pred.bounded_ty.id)
1340+
.map(|d| (d.base_res(), d.unresolved_segments()))
1341+
{
1342+
Some((Res::Def(DefKind::TyParam, def_id), 0))
1343+
if bound_pred.bound_generic_params.is_empty() =>
1344+
{
1345+
generics
1346+
.params
1347+
.iter()
1348+
.find(|p| def_id == self.resolver.local_def_id(p.id).to_def_id())
1349+
.is_some()
13561350
}
1351+
// Either the `bounded_ty` is not a plain type parameter, or
1352+
// it's not found in the generic type parameters list.
1353+
_ => false,
1354+
}
1355+
};
1356+
// We only need to compute this once per `WherePredicate`, but don't
1357+
// need to compute this at all unless there is a Maybe bound.
1358+
let mut is_param: Option<bool> = None;
1359+
for bound in &bound_pred.bounds {
1360+
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
1361+
continue;
1362+
}
1363+
let is_param = *is_param.get_or_insert_with(compute_is_param);
1364+
if !is_param {
1365+
self.diagnostic().span_err(
1366+
bound.span(),
1367+
"`?Trait` bounds are only permitted at the \
1368+
point where a type parameter is declared",
1369+
);
13571370
}
13581371
}
13591372
}

compiler/rustc_ast_lowering/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ pub trait ResolverAstLowering {
166166
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
167167

168168
/// Obtains resolution for a `NodeId` with a single resolution.
169-
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
169+
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
170170

171171
/// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
172172
fn get_import_res(&mut self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
124124
ty::ReVar(vid) => {
125125
// Find something that we can name
126126
let upper_bound = self.approx_universal_upper_bound(vid);
127-
self.definitions[upper_bound].external_name.unwrap_or(region)
127+
let upper_bound = &self.definitions[upper_bound];
128+
match upper_bound.external_name {
129+
Some(reg) => reg,
130+
None => {
131+
// Nothing exact found, so we pick the first one that we find.
132+
let scc = self.constraint_sccs.scc(vid);
133+
for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
134+
match self.definitions[vid].external_name {
135+
None => {}
136+
Some(&ty::ReStatic) => {}
137+
Some(region) => return region,
138+
}
139+
}
140+
region
141+
}
142+
}
128143
}
129144
_ => region,
130145
})

compiler/rustc_mir_transform/src/generator.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -342,15 +342,16 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
342342
let source_info = data.terminator().source_info;
343343
// We must assign the value first in case it gets declared dead below
344344
data.statements.extend(self.make_state(state_idx, v, source_info));
345-
let state = if let Some((resume, resume_arg)) = resume {
345+
let state = if let Some((resume, mut resume_arg)) = resume {
346346
// Yield
347347
let state = 3 + self.suspension_points.len();
348348

349349
// The resume arg target location might itself be remapped if its base local is
350350
// live across a yield.
351351
let resume_arg =
352352
if let Some(&(ty, variant, idx)) = self.remap.get(&resume_arg.local) {
353-
self.make_field(variant, idx, ty)
353+
replace_base(&mut resume_arg, self.make_field(variant, idx, ty), self.tcx);
354+
resume_arg
354355
} else {
355356
resume_arg
356357
};

compiler/rustc_resolve/src/diagnostics.rs

+109-31
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,15 @@ impl<'a> Resolver<'a> {
973973

974974
let import_suggestions =
975975
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
976-
show_candidates(err, None, &import_suggestions, false, true);
976+
show_candidates(
977+
&self.definitions,
978+
self.session,
979+
err,
980+
None,
981+
&import_suggestions,
982+
false,
983+
true,
984+
);
977985

978986
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
979987
let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
@@ -1713,6 +1721,8 @@ fn find_span_immediately_after_crate_name(
17131721
/// entities with that name in all crates. This method allows outputting the
17141722
/// results of this search in a programmer-friendly way
17151723
crate fn show_candidates(
1724+
definitions: &rustc_hir::definitions::Definitions,
1725+
session: &Session,
17161726
err: &mut DiagnosticBuilder<'_>,
17171727
// This is `None` if all placement locations are inside expansions
17181728
use_placement_span: Option<Span>,
@@ -1724,43 +1734,111 @@ crate fn show_candidates(
17241734
return;
17251735
}
17261736

1737+
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
1738+
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
1739+
1740+
candidates.iter().for_each(|c| {
1741+
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
1742+
.push((path_names_to_string(&c.path), c.descr, c.did))
1743+
});
1744+
17271745
// we want consistent results across executions, but candidates are produced
17281746
// by iterating through a hash map, so make sure they are ordered:
1729-
let mut path_strings: Vec<_> =
1730-
candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
1747+
for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
1748+
path_strings.sort_by(|a, b| a.0.cmp(&b.0));
1749+
let core_path_strings =
1750+
path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
1751+
path_strings.extend(core_path_strings);
1752+
path_strings.dedup_by(|a, b| a.0 == b.0);
1753+
}
1754+
1755+
if !accessible_path_strings.is_empty() {
1756+
let (determiner, kind) = if accessible_path_strings.len() == 1 {
1757+
("this", accessible_path_strings[0].1)
1758+
} else {
1759+
("one of these", "items")
1760+
};
17311761

1732-
path_strings.sort();
1733-
let core_path_strings =
1734-
path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
1735-
path_strings.extend(core_path_strings);
1736-
path_strings.dedup();
1762+
let instead = if instead { " instead" } else { "" };
1763+
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
17371764

1738-
let (determiner, kind) = if candidates.len() == 1 {
1739-
("this", candidates[0].descr)
1740-
} else {
1741-
("one of these", "items")
1742-
};
1743-
1744-
let instead = if instead { " instead" } else { "" };
1745-
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
1746-
1747-
if let Some(span) = use_placement_span {
1748-
for candidate in &mut path_strings {
1749-
// produce an additional newline to separate the new use statement
1750-
// from the directly following item.
1751-
let additional_newline = if found_use { "" } else { "\n" };
1752-
*candidate = format!("use {};\n{}", candidate, additional_newline);
1753-
}
1765+
if let Some(span) = use_placement_span {
1766+
for candidate in &mut accessible_path_strings {
1767+
// produce an additional newline to separate the new use statement
1768+
// from the directly following item.
1769+
let additional_newline = if found_use { "" } else { "\n" };
1770+
candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline);
1771+
}
17541772

1755-
err.span_suggestions(span, &msg, path_strings.into_iter(), Applicability::Unspecified);
1756-
} else {
1757-
msg.push(':');
1773+
err.span_suggestions(
1774+
span,
1775+
&msg,
1776+
accessible_path_strings.into_iter().map(|a| a.0),
1777+
Applicability::Unspecified,
1778+
);
1779+
} else {
1780+
msg.push(':');
17581781

1759-
for candidate in path_strings {
1760-
msg.push('\n');
1761-
msg.push_str(&candidate);
1782+
for candidate in accessible_path_strings {
1783+
msg.push('\n');
1784+
msg.push_str(&candidate.0);
1785+
}
1786+
1787+
err.note(&msg);
17621788
}
1789+
} else {
1790+
assert!(!inaccessible_path_strings.is_empty());
1791+
1792+
if inaccessible_path_strings.len() == 1 {
1793+
let (name, descr, def_id) = &inaccessible_path_strings[0];
1794+
let msg = format!("{} `{}` exists but is inaccessible", descr, name);
1795+
1796+
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
1797+
let span = definitions.def_span(local_def_id);
1798+
let span = session.source_map().guess_head_span(span);
1799+
let mut multi_span = MultiSpan::from_span(span);
1800+
multi_span.push_span_label(span, "not accessible".to_string());
1801+
err.span_note(multi_span, &msg);
1802+
} else {
1803+
err.note(&msg);
1804+
}
1805+
} else {
1806+
let (_, descr_first, _) = &inaccessible_path_strings[0];
1807+
let descr = if inaccessible_path_strings
1808+
.iter()
1809+
.skip(1)
1810+
.all(|(_, descr, _)| descr == descr_first)
1811+
{
1812+
format!("{}", descr_first)
1813+
} else {
1814+
"item".to_string()
1815+
};
1816+
1817+
let mut msg = format!("these {}s exist but are inaccessible", descr);
1818+
let mut has_colon = false;
17631819

1764-
err.note(&msg);
1820+
let mut spans = Vec::new();
1821+
for (name, _, def_id) in &inaccessible_path_strings {
1822+
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
1823+
let span = definitions.def_span(local_def_id);
1824+
let span = session.source_map().guess_head_span(span);
1825+
spans.push((name, span));
1826+
} else {
1827+
if !has_colon {
1828+
msg.push(':');
1829+
has_colon = true;
1830+
}
1831+
msg.push('\n');
1832+
msg.push_str(name);
1833+
}
1834+
}
1835+
1836+
let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
1837+
for (name, span) in spans {
1838+
multi_span.push_span_label(span, format!("`{}`: not accessible", name));
1839+
}
1840+
1841+
err.span_note(multi_span, &msg);
1842+
}
17651843
}
17661844
}

compiler/rustc_resolve/src/lib.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ impl ResolverAstLowering for Resolver<'_> {
11521152
self.legacy_const_generic_args(expr)
11531153
}
11541154

1155-
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes> {
1155+
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
11561156
self.partial_res_map.get(&id).cloned()
11571157
}
11581158

@@ -2969,7 +2969,15 @@ impl<'a> Resolver<'a> {
29692969
(None, false)
29702970
};
29712971
if !candidates.is_empty() {
2972-
diagnostics::show_candidates(&mut err, span, &candidates, instead, found_use);
2972+
diagnostics::show_candidates(
2973+
&self.definitions,
2974+
self.session,
2975+
&mut err,
2976+
span,
2977+
&candidates,
2978+
instead,
2979+
found_use,
2980+
);
29732981
} else if let Some((span, msg, sugg, appl)) = suggestion {
29742982
err.span_suggestion(span, msg, sugg, appl);
29752983
}

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2137,7 +2137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21372137
idx_t
21382138
} else {
21392139
let base_t = self.structurally_resolved_type(base.span, base_t);
2140-
match self.lookup_indexing(expr, base, base_t, idx_t) {
2140+
match self.lookup_indexing(expr, base, base_t, idx, idx_t) {
21412141
Some((index_ty, element_ty)) => {
21422142
// two-phase not needed because index_ty is never mutable
21432143
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);

0 commit comments

Comments
 (0)