Auto merge of #103151 - matthiaskrgr:rollup-t3mmnsg, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #102454 (Suggest parentheses for possible range method calling) - #102466 (only allow `ConstEquate` with `feature(gce)`) - #102945 (Do not register placeholder `RegionOutlives` obligations when `considering_regions` is false) - #103091 (rustdoc: remove unused HTML class `sidebar-title`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9c2797de22
@ -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
|
||||
|
@ -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::{
|
||||
@ -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;
|
||||
@ -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>,
|
||||
@ -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!(
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
@ -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![]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
@ -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"]
|
||||
|
@ -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"]
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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 {}
|
||||
|
@ -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;
|
||||
@ -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'
|
||||
@ -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 {
|
||||
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
// @has foo/struct.Foo.html
|
||||
// @has - '//h2[@id="fields"]' 'Tuple Fields'
|
||||
// @has - '//h3[@class="sidebar-title"]/a[@href="#fields"]' 'Tuple Fields'
|
||||
// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Tuple Fields'
|
||||
// @has - '//*[@id="structfield.0"]' '0: u32'
|
||||
// @has - '//*[@id="main-content"]/div[@class="docblock"]' 'hello'
|
||||
// @!has - '//*[@id="structfield.1"]' ''
|
||||
|
29
src/test/ui/higher-rank-trait-bounds/issue-100689.rs
Normal file
29
src/test/ui/higher-rank-trait-bounds/issue-100689.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// check-pass
|
||||
|
||||
struct Foo<'a> {
|
||||
foo: &'a mut usize,
|
||||
}
|
||||
|
||||
trait Bar<'a> {
|
||||
type FooRef<'b>
|
||||
where
|
||||
'a: 'b;
|
||||
fn uwu(foo: Foo<'a>, f: impl for<'b> FnMut(Self::FooRef<'b>));
|
||||
}
|
||||
impl<'a> Bar<'a> for () {
|
||||
type FooRef<'b>
|
||||
=
|
||||
&'b Foo<'a>
|
||||
where
|
||||
'a : 'b,
|
||||
;
|
||||
|
||||
fn uwu(
|
||||
foo: Foo<'a>,
|
||||
mut f: impl for<'b> FnMut(&'b Foo<'a>), //relevant part
|
||||
) {
|
||||
f(&foo);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
32
src/test/ui/higher-rank-trait-bounds/issue-102899.rs
Normal file
32
src/test/ui/higher-rank-trait-bounds/issue-102899.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// check-pass
|
||||
|
||||
pub trait BufferTrait<'buffer> {
|
||||
type Subset<'channel>
|
||||
where
|
||||
'buffer: 'channel;
|
||||
|
||||
fn for_each_subset<F>(&self, f: F)
|
||||
where
|
||||
F: for<'channel> Fn(Self::Subset<'channel>);
|
||||
}
|
||||
|
||||
pub struct SomeBuffer<'buffer> {
|
||||
samples: &'buffer [()],
|
||||
}
|
||||
|
||||
impl<'buffer> BufferTrait<'buffer> for SomeBuffer<'buffer> {
|
||||
type Subset<'subset> = Subset<'subset> where 'buffer: 'subset;
|
||||
|
||||
fn for_each_subset<F>(&self, _f: F)
|
||||
where
|
||||
F: for<'subset> Fn(Subset<'subset>),
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Subset<'subset> {
|
||||
buffer: &'subset [()],
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,7 +1,76 @@
|
||||
#![allow(unused)]
|
||||
fn main() {
|
||||
let arr = &[0,1,2,3];
|
||||
for _i in 0..arr.len().rev() { //~ERROR not an iterator
|
||||
// The above error used to say “the method `rev` exists for type `usize`”.
|
||||
// This regression test ensures it doesn't say that any more.
|
||||
}
|
||||
let arr = &[0, 1, 2, 3];
|
||||
for _i in 0..arr.len().rev() {
|
||||
//~^ ERROR can't call method
|
||||
//~| surround the range in parentheses
|
||||
// The above error used to say “the method `rev` exists for type `usize`”.
|
||||
// This regression test ensures it doesn't say that any more.
|
||||
}
|
||||
|
||||
// Test for #102396
|
||||
for i in 1..11.rev() {
|
||||
//~^ ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
let end: usize = 10;
|
||||
for i in 1..end.rev() {
|
||||
//~^ ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
for i in 1..(end + 1).rev() {
|
||||
//~^ ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
if 1..(end + 1).is_empty() {
|
||||
//~^ ERROR can't call method
|
||||
//~| ERROR mismatched types [E0308]
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
if 1..(end + 1).is_sorted() {
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
let _res: i32 = 3..6.take(2).sum();
|
||||
//~^ ERROR can't call method
|
||||
//~| ERROR mismatched types [E0308]
|
||||
//~| HELP surround the range in parentheses
|
||||
|
||||
let _sum: i32 = 3..6.sum();
|
||||
//~^ ERROR can't call method
|
||||
//~| ERROR mismatched types [E0308]
|
||||
//~| HELP surround the range in parentheses
|
||||
|
||||
let a = 1 as usize;
|
||||
let b = 10 as usize;
|
||||
|
||||
for _a in a..=b.rev() {
|
||||
//~^ ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
}
|
||||
|
||||
let _res = ..10.contains(3);
|
||||
//~^ ERROR can't call method
|
||||
//~| HELP surround the range in parentheses
|
||||
|
||||
if 1..end.error_method() {
|
||||
//~^ ERROR no method named `error_method`
|
||||
//~| ERROR mismatched types [E0308]
|
||||
// Won't suggest
|
||||
}
|
||||
|
||||
let _res = b.take(1)..a;
|
||||
//~^ ERROR `usize` is not an iterator
|
||||
|
||||
let _res: i32 = ..6.take(2).sum();
|
||||
//~^ can't call method `take` on ambiguous numeric type
|
||||
//~| ERROR mismatched types [E0308]
|
||||
//~| HELP you must specify a concrete type for this numeric value
|
||||
// Won't suggest because `RangeTo` dest not implemented `take`
|
||||
}
|
||||
|
@ -1,13 +1,201 @@
|
||||
error[E0599]: `usize` is not an iterator
|
||||
--> $DIR/issue-90315.rs:3:26
|
||||
error[E0689]: can't call method `rev` on type `usize`
|
||||
--> $DIR/issue-90315.rs:4:28
|
||||
|
|
||||
LL | for _i in 0..arr.len().rev() {
|
||||
| ^^^ `usize` is not an iterator
|
||||
LL | for _i in 0..arr.len().rev() {
|
||||
| ^^^ can't call method `rev` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `rev` function
|
||||
|
|
||||
LL | for _i in (0..arr.len()).rev() {
|
||||
| + +
|
||||
|
||||
error[E0689]: can't call method `rev` on type `{integer}`
|
||||
--> $DIR/issue-90315.rs:12:20
|
||||
|
|
||||
LL | for i in 1..11.rev() {
|
||||
| ^^^ can't call method `rev` on type `{integer}`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `rev` function
|
||||
|
|
||||
LL | for i in (1..11).rev() {
|
||||
| + +
|
||||
|
||||
error[E0689]: can't call method `rev` on type `usize`
|
||||
--> $DIR/issue-90315.rs:18:21
|
||||
|
|
||||
LL | for i in 1..end.rev() {
|
||||
| ^^^ can't call method `rev` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `rev` function
|
||||
|
|
||||
LL | for i in (1..end).rev() {
|
||||
| + +
|
||||
|
||||
error[E0689]: can't call method `rev` on type `usize`
|
||||
--> $DIR/issue-90315.rs:23:27
|
||||
|
|
||||
LL | for i in 1..(end + 1).rev() {
|
||||
| ^^^ can't call method `rev` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `rev` function
|
||||
|
|
||||
LL | for i in (1..(end + 1)).rev() {
|
||||
| + +
|
||||
|
||||
error[E0689]: can't call method `is_empty` on type `usize`
|
||||
--> $DIR/issue-90315.rs:28:21
|
||||
|
|
||||
LL | if 1..(end + 1).is_empty() {
|
||||
| ^^^^^^^^ can't call method `is_empty` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `is_empty` function
|
||||
|
|
||||
LL | if (1..(end + 1)).is_empty() {
|
||||
| + +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:28:8
|
||||
|
|
||||
LL | if 1..(end + 1).is_empty() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found struct `std::ops::Range<{integer}>`
|
||||
|
||||
error[E0689]: can't call method `is_sorted` on type `usize`
|
||||
--> $DIR/issue-90315.rs:34:21
|
||||
|
|
||||
LL | if 1..(end + 1).is_sorted() {
|
||||
| ^^^^^^^^^ can't call method `is_sorted` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `is_sorted` function
|
||||
|
|
||||
LL | if (1..(end + 1)).is_sorted() {
|
||||
| + +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:34:8
|
||||
|
|
||||
LL | if 1..(end + 1).is_sorted() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found struct `std::ops::Range<{integer}>`
|
||||
|
||||
error[E0689]: can't call method `take` on type `{integer}`
|
||||
--> $DIR/issue-90315.rs:40:26
|
||||
|
|
||||
LL | let _res: i32 = 3..6.take(2).sum();
|
||||
| ^^^^ can't call method `take` on type `{integer}`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `take` function
|
||||
|
|
||||
LL | let _res: i32 = (3..6).take(2).sum();
|
||||
| + +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:40:21
|
||||
|
|
||||
LL | let _res: i32 = 3..6.take(2).sum();
|
||||
| --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found struct `std::ops::Range<{integer}>`
|
||||
|
||||
error[E0689]: can't call method `sum` on type `{integer}`
|
||||
--> $DIR/issue-90315.rs:45:26
|
||||
|
|
||||
LL | let _sum: i32 = 3..6.sum();
|
||||
| ^^^ can't call method `sum` on type `{integer}`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `sum` function
|
||||
|
|
||||
LL | let _sum: i32 = (3..6).sum();
|
||||
| + +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:45:21
|
||||
|
|
||||
LL | let _sum: i32 = 3..6.sum();
|
||||
| --- ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found struct `std::ops::Range<{integer}>`
|
||||
|
||||
error[E0689]: can't call method `rev` on type `usize`
|
||||
--> $DIR/issue-90315.rs:53:21
|
||||
|
|
||||
LL | for _a in a..=b.rev() {
|
||||
| ^^^ can't call method `rev` on type `usize`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `rev` function
|
||||
|
|
||||
LL | for _a in (a..=b).rev() {
|
||||
| + +
|
||||
|
||||
error[E0689]: can't call method `contains` on type `{integer}`
|
||||
--> $DIR/issue-90315.rs:58:21
|
||||
|
|
||||
LL | let _res = ..10.contains(3);
|
||||
| ^^^^^^^^ can't call method `contains` on type `{integer}`
|
||||
|
|
||||
help: you must surround the range in parentheses to call its `contains` function
|
||||
|
|
||||
LL | let _res = (..10).contains(3);
|
||||
| + +
|
||||
|
||||
error[E0599]: no method named `error_method` found for type `usize` in the current scope
|
||||
--> $DIR/issue-90315.rs:62:15
|
||||
|
|
||||
LL | if 1..end.error_method() {
|
||||
| ^^^^^^^^^^^^ method not found in `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:62:8
|
||||
|
|
||||
LL | if 1..end.error_method() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found struct `std::ops::Range<{integer}>`
|
||||
|
||||
error[E0599]: `usize` is not an iterator
|
||||
--> $DIR/issue-90315.rs:68:18
|
||||
|
|
||||
LL | let _res = b.take(1)..a;
|
||||
| ^^^^ `usize` is not an iterator
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`usize: Iterator`
|
||||
which is required by `&mut usize: Iterator`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0689]: can't call method `take` on ambiguous numeric type `{integer}`
|
||||
--> $DIR/issue-90315.rs:71:25
|
||||
|
|
||||
LL | let _res: i32 = ..6.take(2).sum();
|
||||
| ^^^^
|
||||
|
|
||||
help: you must specify a concrete type for this numeric value, like `i32`
|
||||
|
|
||||
LL | let _res: i32 = ..6_i32.take(2).sum();
|
||||
| ~~~~~
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-90315.rs:71:21
|
||||
|
|
||||
LL | let _res: i32 = ..6.take(2).sum();
|
||||
| --- ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found struct `RangeTo<_>`
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0599, E0689.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user