Skip to content

Rollup of 7 pull requests #102247

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

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bcf780e
Recover error strings on Unix from_lossy_utf8
workingjubilee Jul 22, 2022
71f8fd5
improve infer var handling for implied bounds
lcnr Sep 19, 2022
72a2102
add test
lcnr Sep 19, 2022
8a2c0cc
fix #102087, Suggest Default::default() when binding isn't initialized
chenyukang Sep 23, 2022
719e41e
cleanup
chenyukang Sep 23, 2022
3d01d43
rustdoc: Stabilize --diagnostic-width
ehuss Sep 24, 2022
2bfab8e
add LetVisitor for more accurate span
chenyukang Sep 24, 2022
21b9222
suggest assign value for let without a type decl
chenyukang Sep 24, 2022
a0be6c4
rustdoc: remove unused CSS `#main-content > .line-numbers`
notriddle Sep 24, 2022
55b11cf
rustdoc: remove unused CSS `.summary`
notriddle Sep 24, 2022
59c4a92
Resolve async fn signature even without body (in trait)
compiler-errors Sep 22, 2022
3d7e9a7
Only record extra lifetime params for async trait fn with no body
compiler-errors Sep 23, 2022
e87fcc0
Add test
compiler-errors Sep 24, 2022
7209486
Rollup merge of #99609 - workingjubilee:lossy-unix-strerror, r=thomcc
matthiaskrgr Sep 24, 2022
02beea3
Rollup merge of #102016 - lcnr:given-OutlivesEnvironment, r=jackh726
matthiaskrgr Sep 24, 2022
6aa4656
Rollup merge of #102161 - compiler-errors:issue-102138, r=tmandry
matthiaskrgr Sep 24, 2022
66fe5d3
Rollup merge of #102184 - chenyukang:fix-102087-add-binding-sugg, r=n…
matthiaskrgr Sep 24, 2022
ea8e7fb
Rollup merge of #102216 - ehuss:rustdoc-diagnostic-width, r=notriddle
matthiaskrgr Sep 24, 2022
5a70396
Rollup merge of #102240 - notriddle:notriddle/main-line-numbers, r=Gu…
matthiaskrgr Sep 24, 2022
0416589
Rollup merge of #102242 - notriddle:notriddle/summary, r=GuillaumeGomez
matthiaskrgr Sep 24, 2022
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
70 changes: 70 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
visitor.visit_body(&body);

let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action
{
Expand Down Expand Up @@ -396,6 +397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.count()
== 0
{
show_assign_sugg = true;
"isn't initialized"
} else {
"is possibly-uninitialized"
Expand Down Expand Up @@ -446,10 +448,78 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
}

err.span_label(decl_span, "binding declared here but left uninitialized");
if show_assign_sugg {
struct LetVisitor {
decl_span: Span,
sugg_span: Option<Span>,
}

impl<'v> Visitor<'v> for LetVisitor {
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
if self.sugg_span.is_some() {
return;
}
if let hir::StmtKind::Local(hir::Local {
span, ty, init: None, ..
}) = &ex.kind && span.contains(self.decl_span) {
self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
}
hir::intravisit::walk_stmt(self, ex);
}
}

let mut visitor = LetVisitor { decl_span, sugg_span: None };
visitor.visit_body(&body);
if let Some(span) = visitor.sugg_span {
self.suggest_assign_value(&mut err, moved_place, span);
}
}
err
}

fn suggest_assign_value(
&self,
err: &mut Diagnostic,
moved_place: PlaceRef<'tcx>,
sugg_span: Span,
) {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());

let tcx = self.infcx.tcx;
let implements_default = |ty, param_env| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
tcx.infer_ctxt().enter(|infcx| {
infcx
.type_implements_trait(default_trait, ty, ty::List::empty(), param_env)
.may_apply()
})
};

let assign_value = match ty.kind() {
ty::Bool => "false",
ty::Float(_) => "0.0",
ty::Int(_) | ty::Uint(_) => "0",
ty::Never | ty::Error(_) => "",
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
_ => "todo!()",
};

if !assign_value.is_empty() {
err.span_suggestion_verbose(
sugg_span.shrink_to_hi(),
format!("consider assigning a value"),
format!(" = {}", assign_value),
Applicability::MaybeIncorrect,
);
}
}

fn suggest_borrow_fn_like(
&self,
err: &mut Diagnostic,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_infer/src/infer/outlives/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub struct OutlivesEnvironment<'tcx> {
}

/// Builder of OutlivesEnvironment.
#[derive(Debug)]
struct OutlivesEnvironmentBuilder<'tcx> {
param_env: ty::ParamEnv<'tcx>,
region_relation: TransitiveRelationBuilder<Region<'tcx>>,
Expand Down Expand Up @@ -109,6 +110,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {

impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
#[inline]
#[instrument(level = "debug")]
fn build(self) -> OutlivesEnvironment<'tcx> {
OutlivesEnvironment {
param_env: self.param_env,
Expand Down
73 changes: 37 additions & 36 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
sig.decl.has_self(),
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
&sig.decl.output,
)
);

this.record_lifetime_params_for_async(
fn_id,
sig.header.asyncness.opt_return_id(),
);
},
);
return;
Expand Down Expand Up @@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
},
);

// Construct the list of in-scope lifetime parameters for async lowering.
// We include all lifetime parameters, either named or "Fresh".
// The order of those parameters does not matter, as long as it is
// deterministic.
if let Some((async_node_id, _)) = async_node_id {
let mut extra_lifetime_params = this
.r
.extra_lifetime_params_map
.get(&fn_id)
.cloned()
.unwrap_or_default();
for rib in this.lifetime_ribs.iter().rev() {
extra_lifetime_params.extend(
rib.bindings
.iter()
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
);
match rib.kind {
LifetimeRibKind::Item => break,
LifetimeRibKind::AnonymousCreateParameter {
binder, ..
} => {
if let Some(earlier_fresh) =
this.r.extra_lifetime_params_map.get(&binder)
{
extra_lifetime_params.extend(earlier_fresh);
}
}
_ => {}
}
}
this.r
.extra_lifetime_params_map
.insert(async_node_id, extra_lifetime_params);
}
this.record_lifetime_params_for_async(fn_id, async_node_id);

if let Some(body) = body {
// Ignore errors in function bodies if this is rustdoc
Expand Down Expand Up @@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Some((ident.name, ns)),
)
}

/// Construct the list of in-scope lifetime parameters for async lowering.
/// We include all lifetime parameters, either named or "Fresh".
/// The order of those parameters does not matter, as long as it is
/// deterministic.
fn record_lifetime_params_for_async(
&mut self,
fn_id: NodeId,
async_node_id: Option<(NodeId, Span)>,
) {
if let Some((async_node_id, _)) = async_node_id {
let mut extra_lifetime_params =
self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
for rib in self.lifetime_ribs.iter().rev() {
extra_lifetime_params.extend(
rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
);
match rib.kind {
LifetimeRibKind::Item => break,
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
extra_lifetime_params.extend(earlier_fresh);
}
}
_ => {}
}
}
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
}
}
}

struct LifetimeCountVisitor<'a, 'b> {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
/// Note that this may cause outlives obligations to be injected
/// into the inference context with this body-id.
/// - `ty`, the type that we are supposed to assume is WF.
#[instrument(level = "debug", skip(self, param_env, body_id))]
#[instrument(level = "debug", skip(self, param_env, body_id), ret)]
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
Expand All @@ -71,6 +71,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
let TypeOpOutput { output, constraints, .. } = result;

if let Some(constraints) = constraints {
debug!(?constraints);
// Instantiation may have produced new inference variables and constraints on those
// variables. Process these constraints.
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);
Expand Down
69 changes: 36 additions & 33 deletions compiler/rustc_traits/src/implied_outlives_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>(
let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
let mut wf_args = vec![ty.into()];

let mut implied_bounds = vec![];
let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
vec![];

let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);

Expand All @@ -65,41 +66,28 @@ fn compute_implied_outlives_bounds<'tcx>(
// than the ultimate set. (Note: normally there won't be
// unresolved inference variables here anyway, but there might be
// during typeck under some circumstances.)
//
// FIXME(@lcnr): It's not really "always fine", having fewer implied
// bounds can be backward incompatible, e.g. #101951 was caused by
// us not dealing with inference vars in `TypeOutlives` predicates.
let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
.unwrap_or_default();

// N.B., all of these predicates *ought* to be easily proven
// true. In fact, their correctness is (mostly) implied by
// other parts of the program. However, in #42552, we had
// an annoying scenario where:
//
// - Some `T::Foo` gets normalized, resulting in a
// variable `_1` and a `T: Trait<Foo=_1>` constraint
// (not sure why it couldn't immediately get
// solved). This result of `_1` got cached.
// - These obligations were dropped on the floor here,
// rather than being registered.
// - Then later we would get a request to normalize
// `T::Foo` which would result in `_1` being used from
// the cache, but hence without the `T: Trait<Foo=_1>`
// constraint. As a result, `_1` never gets resolved,
// and we get an ICE (in dropck).
//
// Therefore, we register any predicates involving
// inference variables. We restrict ourselves to those
// involving inference variables both for efficiency and
// to avoids duplicate errors that otherwise show up.
// While these predicates should all be implied by other parts of
// the program, they are still relevant as they may constrain
// inference variables, which is necessary to add the correct
// implied bounds in some cases, mostly when dealing with projections.
fulfill_cx.register_predicate_obligations(
infcx,
obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
);

// From the full set of obligations, just filter down to the
// region relationships.
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
assert!(!obligation.has_escaping_bound_vars());
match obligation.predicate.kind().no_bound_vars() {
None => vec![],
None => None,
Some(pred) => match pred {
ty::PredicateKind::Trait(..)
| ty::PredicateKind::Subtype(..)
Expand All @@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>(
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::WellFormed(arg) => {
wf_args.push(arg);
vec![]
None
}

ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
Some(ty::OutlivesPredicate(r_a.into(), r_b))
}

ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
let ty_a = infcx.resolve_vars_if_possible(ty_a);
let mut components = smallvec![];
push_outlives_components(tcx, ty_a, &mut components);
implied_bounds_from_components(r_b, components)
Some(ty::OutlivesPredicate(ty_a.into(), r_b))
}
},
}
Expand All @@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>(
// Ensure that those obligations that we had to solve
// get solved *here*.
match fulfill_cx.select_all_or_error(infcx).as_slice() {
[] => Ok(implied_bounds),
_ => Err(NoSolution),
[] => (),
_ => return Err(NoSolution),
}

// We lazily compute the outlives components as
// `select_all_or_error` constrains inference variables.
let implied_bounds = outlives_bounds
.into_iter()
.flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
ty::GenericArgKind::Type(ty_a) => {
let ty_a = infcx.resolve_vars_if_possible(ty_a);
let mut components = smallvec![];
push_outlives_components(tcx, ty_a, &mut components);
implied_bounds_from_components(r_b, components)
}
ty::GenericArgKind::Const(_) => unreachable!(),
})
.collect();

Ok(implied_bounds)
}

/// When we have an implied bound that `T: 'a`, we can further break
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_typeck/src/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ pub(crate) fn compare_impl_method<'tcx>(
///
/// Finally we register each of these predicates as an obligation and check that
/// they hold.
#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
fn compare_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &AssocItem,
Expand Down
4 changes: 3 additions & 1 deletion library/std/src/sys/unix/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ pub fn error_string(errno: i32) -> String {
}

let p = p as *const _;
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
// We can't always expect a UTF-8 environment. When we don't get that luxury,
// it's better to give a low-quality error message than none at all.
String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into()
}
}

Expand Down
8 changes: 0 additions & 8 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -1130,10 +1130,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
font-size: 1rem;
}

.summary {
padding-right: 0px;
}

pre.rust .question-mark {
font-weight: bold;
}
Expand Down Expand Up @@ -1917,10 +1913,6 @@ in storage.js plus the media query with (min-width: 701px)
border-bottom: 1px solid;
}

#main-content > .line-numbers {
margin-top: 0;
}

.notable-traits .notable-traits-tooltiptext {
left: 0;
top: 100%;
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ fn opts() -> Vec<RustcOptGroup> {
"human|json|short",
)
}),
unstable("diagnostic-width", |o| {
stable("diagnostic-width", |o| {
o.optopt(
"",
"diagnostic-width",
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/diagnostic-width.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -Zunstable-options --diagnostic-width=10
// compile-flags: --diagnostic-width=10
#![deny(rustdoc::bare_urls)]

/// This is a long line that contains a http://link.com
Expand Down
Loading