Skip to content

Commit

Permalink
Auto merge of rust-lang#100174 - Dylan-DPC:rollup-wnskbk6, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - rust-lang#99835 (Suggest adding/removing `ref` for binding patterns)
 - rust-lang#100155 (Use `node_type_opt` to skip over generics that were not expected)
 - rust-lang#100157 (rustdoc: use `collect()` instead of repeatedly pushing)
 - rust-lang#100158 (kmc-solid: Add a stub implementation of rust-lang#98246 (`File::set_times`))
 - rust-lang#100166 (Remove more Clean trait implementations)
 - rust-lang#100168 (Improve diagnostics for `const a: = expr;`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Aug 5, 2022
2 parents d77da9d + e7ed844 commit affe0d3
Show file tree
Hide file tree
Showing 30 changed files with 414 additions and 162 deletions.
30 changes: 19 additions & 11 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1179,39 +1179,47 @@ impl<'a> Parser<'a> {

// Parse the type of a `const` or `static mut?` item.
// That is, the `":" $ty` fragment.
let ty = if self.eat(&token::Colon) {
self.parse_ty()?
} else {
self.recover_missing_const_type(id, m)
let ty = match (self.eat(&token::Colon), self.check(&token::Eq) | self.check(&token::Semi))
{
// If there wasn't a `:` or the colon was followed by a `=` or `;` recover a missing type.
(true, false) => self.parse_ty()?,
(colon, _) => self.recover_missing_const_type(colon, m),
};

let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
self.expect_semi()?;
Ok((id, ty, expr))
}

/// We were supposed to parse `:` but the `:` was missing.
/// We were supposed to parse `":" $ty` but the `:` or the type was missing.
/// This means that the type is missing.
fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> {
fn recover_missing_const_type(&mut self, colon_present: bool, m: Option<Mutability>) -> P<Ty> {
// Construct the error and stash it away with the hope
// that typeck will later enrich the error with a type.
let kind = match m {
Some(Mutability::Mut) => "static mut",
Some(Mutability::Not) => "static",
None => "const",
};
let mut err = self.struct_span_err(id.span, &format!("missing type for `{kind}` item"));

let colon = match colon_present {
true => "",
false => ":",
};

let span = self.prev_token.span.shrink_to_hi();
let mut err = self.struct_span_err(span, &format!("missing type for `{kind}` item"));
err.span_suggestion(
id.span,
span,
"provide a type for the item",
format!("{id}: <type>"),
format!("{colon} <type>"),
Applicability::HasPlaceholders,
);
err.stash(id.span, StashKey::ItemNoType);
err.stash(span, StashKey::ItemNoType);

// The user intended that the type be inferred,
// so treat this as if the user wrote e.g. `const A: _ = expr;`.
P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID, tokens: None })
P(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
}

/// Parses an enum declaration.
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,13 +1761,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.filter_map(|seg| seg.args.as_ref())
.flat_map(|a| a.args.iter())
{
if let hir::GenericArg::Type(hir_ty) = &arg {
let ty = self.resolve_vars_if_possible(
self.typeck_results.borrow().node_type(hir_ty.hir_id),
);
if ty == predicate.self_ty() {
error.obligation.cause.span = hir_ty.span;
}
if let hir::GenericArg::Type(hir_ty) = &arg
&& let Some(ty) =
self.typeck_results.borrow().node_type_opt(hir_ty.hir_id)
&& self.resolve_vars_if_possible(ty) == predicate.self_ty()
{
error.obligation.cause.span = hir_ty.span;
break;
}
}
}
Expand Down
53 changes: 49 additions & 4 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be.
if var_id != pat.hir_id {
self.check_binding_alt_eq_ty(pat.span, var_id, local_ty, ti);
self.check_binding_alt_eq_ty(ba, pat.span, var_id, local_ty, ti);
}

if let Some(p) = sub {
Expand All @@ -610,7 +610,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
local_ty
}

fn check_binding_alt_eq_ty(&self, span: Span, var_id: HirId, ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
fn check_binding_alt_eq_ty(
&self,
ba: hir::BindingAnnotation,
span: Span,
var_id: HirId,
ty: Ty<'tcx>,
ti: TopInfo<'tcx>,
) {
let var_ty = self.local_ty(span, var_id).decl_ty;
if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
let hir = self.tcx.hir();
Expand All @@ -628,12 +635,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
let pre = if in_match { "in the same arm, " } else { "" };
err.note(&format!("{}a binding must have the same type in all alternatives", pre));
// FIXME: check if `var_ty` and `ty` can be made the same type by adding or removing
// `ref` or `&` to the pattern.
self.suggest_adding_missing_ref_or_removing_ref(
&mut err,
span,
var_ty,
self.resolve_vars_with_obligations(ty),
ba,
);
err.emit();
}
}

fn suggest_adding_missing_ref_or_removing_ref(
&self,
err: &mut Diagnostic,
span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ba: hir::BindingAnnotation,
) {
match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::Unannotated)
if self.can_eq(self.param_env, *inner_ty, actual).is_ok() =>
{
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider adding `ref`",
"ref ",
Applicability::MaybeIncorrect,
);
}
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::Ref)
if self.can_eq(self.param_env, expected, *inner_ty).is_ok() =>
{
err.span_suggestion_verbose(
span.with_hi(span.lo() + BytePos(4)),
"consider removing `ref`",
"",
Applicability::MaybeIncorrect,
);
}
_ => (),
}
}

// Precondition: pat is a Ref(_) pattern
fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) {
let tcx = self.tcx;
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,9 @@ fn infer_placeholder_type<'a>(
match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
Some(mut err) => {
if !ty.references_error() {
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic)
let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" };

// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
// We are typeck and have the real type, so remove that and suggest the actual type.
// FIXME(eddyb) this looks like it should be functionality on `Diagnostic`.
Expand All @@ -816,7 +819,7 @@ fn infer_placeholder_type<'a>(
err.span_suggestion(
span,
&format!("provide a type for the {item}", item = kind),
format!("{}: {}", item_ident, sugg_ty),
format!("{colon} {sugg_ty}"),
Applicability::MachineApplicable,
);
} else {
Expand Down
12 changes: 12 additions & 0 deletions library/std/src/sys/solid/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub struct OpenOptions {
custom_flags: i32,
}

#[derive(Copy, Clone, Debug, Default)]
pub struct FileTimes {}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FilePermissions(c_short);

Expand Down Expand Up @@ -126,6 +129,11 @@ impl FilePermissions {
}
}

impl FileTimes {
pub fn set_accessed(&mut self, _t: SystemTime) {}
pub fn set_modified(&mut self, _t: SystemTime) {}
}

impl FileType {
pub fn is_dir(&self) -> bool {
self.is(abi::S_IFDIR)
Expand Down Expand Up @@ -452,6 +460,10 @@ impl File {
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
unsupported()
}

pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
unsupported()
}
}

impl Drop for File {
Expand Down

0 comments on commit affe0d3

Please sign in to comment.