Skip to content

Rollup of 4 pull requests #103151

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

Merged
merged 11 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,7 @@ hir_analysis_extern_crate_not_idiomatic =
.suggestion = convert it to a `{$msg_code}`

hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`

hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`

hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
89 changes: 87 additions & 2 deletions compiler/rustc_hir_analysis/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! found or is otherwise invalid.

use crate::check::FnCtxt;
use crate::errors;
use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
Expand Down Expand Up @@ -271,7 +272,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};

if self.suggest_constraining_numerical_ty(
if self.suggest_wrapping_range_with_parens(
tcx, actual, source, span, item_name, &ty_str,
) || self.suggest_constraining_numerical_ty(
tcx, actual, source, span, item_kind, item_name, &ty_str,
) {
return None;
Expand Down Expand Up @@ -1202,6 +1205,89 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}

/// Suggest possible range with adding parentheses, for example:
/// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
fn suggest_wrapping_range_with_parens(
&self,
tcx: TyCtxt<'tcx>,
actual: Ty<'tcx>,
source: SelfSource<'tcx>,
span: Span,
item_name: Ident,
ty_str: &str,
) -> bool {
if let SelfSource::MethodCall(expr) = source {
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
if let Node::Expr(parent_expr) = parent {
let lang_item = match parent_expr.kind {
ExprKind::Struct(ref qpath, _, _) => match **qpath {
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
Some(LangItem::RangeToInclusive)
}
_ => None,
},
ExprKind::Call(ref func, _) => match func.kind {
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
Some(LangItem::RangeInclusiveStruct)
}
_ => None,
},
_ => None,
};

if lang_item.is_none() {
continue;
}

let span_included = match parent_expr.kind {
hir::ExprKind::Struct(_, eps, _) => {
eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
}
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
_ => false,
};

if !span_included {
continue;
}

let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
let range_ty =
self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);

let pick = self.probe_for_name(
span,
Mode::MethodCall,
item_name,
IsSuggestion(true),
range_ty,
expr.hir_id,
ProbeScope::AllTraits,
);
if pick.is_ok() {
let range_span = parent_expr.span.with_hi(expr.span.hi());
tcx.sess.emit_err(errors::MissingParentheseInRange {
span,
ty_str: ty_str.to_string(),
method_name: item_name.as_str().to_string(),
add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
func_name: item_name.name.as_str().to_string(),
left: range_span.shrink_to_lo(),
right: range_span.shrink_to_hi(),
}),
});
return true;
}
}
}
}
false
}

fn suggest_constraining_numerical_ty(
&self,
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -1264,7 +1350,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If this is a floating point literal that ends with '.',
// get rid of it to stop this from becoming a member access.
let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);

err.span_suggestion(
lit.span,
&format!(
Expand Down
26 changes: 26 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,29 @@ pub struct ExpectedUsedSymbol {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")]
pub struct MissingParentheseInRange {
#[primary_span]
#[label(hir_analysis::missing_parentheses_in_range)]
pub span: Span,
pub ty_str: String,
pub method_name: String,

#[subdiagnostic]
pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion_verbose(
hir_analysis::add_missing_parentheses_in_range,
applicability = "maybe-incorrect"
)]
pub struct AddMissingParenthesesInRange {
pub func_name: String,
#[suggestion_part(code = "(")]
pub left: Span,
#[suggestion_part(code = ")")]
pub right: Span,
}
27 changes: 14 additions & 13 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}

ty::PredicateKind::RegionOutlives(data) => {
if infcx.considering_regions || data.has_placeholders() {
if infcx.considering_regions {
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
}

Expand Down Expand Up @@ -492,19 +492,20 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}

ty::PredicateKind::ConstEquate(c1, c2) => {
assert!(
self.selcx.tcx().features().generic_const_exprs,
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
);
debug!(?c1, ?c2, "equating consts");
let tcx = self.selcx.tcx();
if tcx.features().generic_const_exprs {
// FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters.
//
// Let's just see where this breaks :shrug:
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind())
{
if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
return ProcessResult::Changed(vec![]);
}
// FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters.
//
// Let's just see where this breaks :shrug:
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind())
{
if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
return ProcessResult::Changed(vec![]);
}
}

Expand Down
24 changes: 13 additions & 11 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,19 +676,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}

ty::PredicateKind::ConstEquate(c1, c2) => {
assert!(
self.tcx().features().generic_const_exprs,
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
);
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");

if self.tcx().features().generic_const_exprs {
// FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters.
//
// Let's just see where this breaks :shrug:
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind())
{
if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
return Ok(EvaluatedToOk);
}
// FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters.
//
// Let's just see where this breaks :shrug:
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind())
{
if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
return Ok(EvaluatedToOk);
}
}

Expand Down
8 changes: 1 addition & 7 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2259,13 +2259,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
}

fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
write!(
buf,
"<h3 class=\"sidebar-title\">\
<a href=\"#{}\">{}</a>\
</h3>",
id, title
);
write!(buf, "<h3><a href=\"#{}\">{}</a></h3>", id, title);
}

fn print_sidebar_block(
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc-gui/sidebar-mobile.goml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
// Force the sidebar open by focusing a link inside it.
// This makes it easier for keyboard users to get to it.
focus: ".sidebar-title a"
focus: ".sidebar-elems h3 a"
assert-css: (".sidebar", {"display": "block", "left": "0px"})
// When we tab out of the sidebar, close it.
focus: ".search-input"
Expand Down
8 changes: 4 additions & 4 deletions src/test/rustdoc/associated-consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub trait Trait {
pub struct Bar;

// @has 'foo/struct.Bar.html'
// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Trait for Bar {
const FOO: u32 = 1;
Expand All @@ -22,7 +22,7 @@ pub enum Foo {
}

// @has 'foo/enum.Foo.html'
// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Trait for Foo {
const FOO: u32 = 1;
Expand All @@ -33,7 +33,7 @@ impl Trait for Foo {
pub struct Baz;

// @has 'foo/struct.Baz.html'
// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Baz {
pub const FOO: u32 = 42;
Expand All @@ -44,7 +44,7 @@ pub enum Quux {
}

// @has 'foo/enum.Quux.html'
// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Quux {
pub const FOO: u32 = 42;
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc/deref-recursive-pathbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path'
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists'

#![crate_name = "foo"]
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc/deref-recursive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar'
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz'

#![crate_name = "foo"]
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/deref-typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c'
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/escape-deref-methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Deref for TitleList {
}

// @has foo/struct.TitleList.html
// @has - '//*[@class="sidebar-title"]' 'Methods from Deref<Target=Vec<Title>>'
// @has - '//div[@class="sidebar-elems"]//h3' 'Methods from Deref<Target=Vec<Title>>'
impl DerefMut for TitleList {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.members
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/negative-impl-sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
pub struct Foo;

// @has foo/struct.Foo.html
// @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#trait-implementations"]' 'Trait Implementations'
// @has - '//*[@class="sidebar-elems"]//section//a' '!Sync'
impl !Sync for Foo {}
18 changes: 9 additions & 9 deletions src/test/rustdoc/sidebar-items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
#![crate_name = "foo"]

// @has foo/trait.Foo.html
// @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-methods"]' 'Required Methods'
// @has - '//*[@class="sidebar-elems"]//section//a' 'bar'
// @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-methods"]' 'Provided Methods'
// @has - '//*[@class="sidebar-elems"]//section//a' 'foo'
// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-consts"]' 'Required Associated Constants'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-consts"]' 'Required Associated Constants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'FOO'
// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-consts"]' 'Provided Associated Constants'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-consts"]' 'Provided Associated Constants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'BAR'
// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-types"]' 'Required Associated Types'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-types"]' 'Required Associated Types'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Output'
// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-types"]' 'Provided Associated Types'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Extra'
pub trait Foo {
const FOO: usize;
Expand All @@ -25,7 +25,7 @@ pub trait Foo {
}

// @has foo/struct.Bar.html
// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u'
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
Expand All @@ -36,7 +36,7 @@ pub struct Bar {
}

// @has foo/enum.En.html
// @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Foo'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Bar'
pub enum En {
Expand All @@ -45,7 +45,7 @@ pub enum En {
}

// @has foo/union.MyUnion.html
// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2'
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/sidebar-links-to-foreign-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#![crate_name = "foo"]

// @has foo/trait.Foo.html
// @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
// @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32'
// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32'
Expand Down
Loading