aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yaml17
-rw-r--r--Cargo.lock76
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs2
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_impl.rs2
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs34
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs3
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs2
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs4
-rw-r--r--crates/ra_assists/src/handlers/move_bounds.rs3
-rw-r--r--crates/ra_hir/src/source_analyzer.rs38
-rw-r--r--crates/ra_hir_def/src/adt.rs20
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs72
-rw-r--r--crates/ra_hir_def/src/body/lower.rs58
-rw-r--r--crates/ra_hir_def/src/data.rs37
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs2
-rw-r--r--crates/ra_hir_def/src/expr.rs33
-rw-r--r--crates/ra_hir_def/src/lang_item.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs14
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs6
-rw-r--r--crates/ra_hir_def/src/path.rs5
-rw-r--r--crates/ra_hir_expand/src/ast_id_map.rs2
-rw-r--r--crates/ra_hir_ty/Cargo.toml2
-rw-r--r--crates/ra_hir_ty/src/db.rs9
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs31
-rw-r--r--crates/ra_hir_ty/src/display.rs26
-rw-r--r--crates/ra_hir_ty/src/expr.rs137
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs2
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs45
-rw-r--r--crates/ra_hir_ty/src/tests.rs46
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs31
-rw-r--r--crates/ra_hir_ty/src/traits.rs27
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs92
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs231
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs4
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs2
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide/src/inlay_hints.rs17
-rw-r--r--crates/ra_ide/src/syntax_tree.rs8
-rw-r--r--crates/ra_ide/src/typing.rs2
-rw-r--r--crates/ra_ide_db/src/defs.rs2
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs36
-rw-r--r--crates/ra_mbe/src/tests.rs20
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs40
-rw-r--r--crates/ra_parser/src/grammar/types.rs15
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs328
-rw-r--r--crates/ra_proc_macro_srv/Cargo.toml5
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs211
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs36
-rw-r--r--crates/ra_proc_macro_srv/src/rustc_server.rs4
-rw-r--r--crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt188
-rw-r--r--crates/ra_proc_macro_srv/src/tests/mod.rs47
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs65
-rw-r--r--crates/ra_prof/src/lib.rs15
-rw-r--r--crates/ra_syntax/src/ast.rs8
-rw-r--r--crates/ra_syntax/src/ast/edit.rs14
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs98
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs553
-rw-r--r--crates/ra_syntax/src/ast/generated/tokens.rs1829
-rw-r--r--crates/ra_syntax/src/ast/make.rs3
-rw-r--r--crates/ra_syntax/src/ast/traits.rs5
-rw-r--r--crates/ra_syntax/src/lib.rs5
-rw-r--r--crates/ra_syntax/src/parsing/lexer.rs77
-rw-r--r--crates/ra_syntax/src/ptr.rs17
-rw-r--r--crates/ra_syntax/test_data/lexer/err/0049_unstarted_raw_string_with_ascii.txt2
-rw-r--r--crates/ra_syntax/test_data/lexer/err/0050_unstarted_raw_byte_string_with_ascii.txt2
-rw-r--r--crates/ra_syntax/test_data/lexer/ok/0005_symbols.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0002_duplicate_shebang.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0004_use_path_bad_segment.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0009_broken_struct_type_parameter.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0011_extern_struct.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0012_broken_lambda.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0013_invalid_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0019_let_recover.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast24
-rw-r--r--crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/err/0025_nope.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0035_use_recover.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0036_partial_use.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0001_array_type_missing_semi.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast34
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0007_type_param_bounds.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0012_type_item_where_clause.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0013_pointer_type_mut.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0014_never_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0017_array_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0020_use_star.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0022_crate_visibility.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0023_placeholder_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0025_slice_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0028_impl_trait_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0032_fn_pointer_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0033_reference_type;.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0043_use_alias.rast30
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0046_singleton_tuple_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0050_fn_decl.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0051_unit_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0052_path_type.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0060_extern_crate.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0063_impl_def_neg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0065_dyn_trait_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0067_crate_path.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0069_use_tree_list_after_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0073_type_item_type_params.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0078_type_item.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0084_paren_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0090_type_param_default.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0104_path_fn_trait_args.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0110_use_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast28
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0117_macro_call_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0123_param_list_vararg.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0131_existential_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast82
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0150_array_attrs.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0151_trait_alias.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0007_extern_crate.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0009_use_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0010_use_path_segments.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0012_visibility.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0014_use_tree.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0015_use_tree.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.rast28
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0020_type_param_bounds.rast24
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0023_static_items.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0024_const_item.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast22
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast36
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_traits.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0031_extern.rast120
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0032_where_for.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0033_label_break.rast16
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast432
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0049_async_block.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast6
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast12
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0060_as_range.rast8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_variadic_fun.rast12
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs12
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs4
-rw-r--r--crates/rust-analyzer/src/world.rs4
-rw-r--r--crates/stdx/src/lib.rs16
-rw-r--r--docs/user/assists.md2
-rw-r--r--editors/code/src/config.ts39
-rw-r--r--editors/code/src/inlay_hints.ts10
-rw-r--r--xtask/src/ast_src.rs417
-rw-r--r--xtask/src/codegen/gen_syntax.rs287
-rw-r--r--xtask/tests/tidy-tests/main.rs11
275 files changed, 3361 insertions, 4290 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 02a3b6228..00f299ff1 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -20,25 +20,14 @@ jobs:
20 name: Audit Rust vulnerabilities 20 name: Audit Rust vulnerabilities
21 runs-on: ubuntu-latest 21 runs-on: ubuntu-latest
22 steps: 22 steps:
23 - name: Install Rust toolchain
24 uses: actions-rs/toolchain@v1
25 with:
26 toolchain: stable
27 profile: minimal
28 override: true
29
30 - name: Checkout repository 23 - name: Checkout repository
31 uses: actions/checkout@v2 24 uses: actions/checkout@v2
32 25
33 - run: sudo chown -R $(whoami):$(id -ng) ~/.cargo/ 26 - uses: actions-rs/[email protected]
34
35 - name: Cache cargo
36 uses: actions/cache@v1
37 with: 27 with:
38 path: ~/.cargo/ 28 crate: cargo-audit
39 key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 29 use-tool-cache: true
40 30
41 - run: cargo install cargo-audit
42 - run: cargo audit 31 - run: cargo audit
43 32
44 rust: 33 rust:
diff --git a/Cargo.lock b/Cargo.lock
index 34f05e83a..975c1aef8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -425,6 +425,17 @@ dependencies = [
425] 425]
426 426
427[[package]] 427[[package]]
428name = "goblin"
429version = "0.2.1"
430source = "registry+https://github.com/rust-lang/crates.io-index"
431checksum = "ddd5e3132801a1ac34ac53b97acde50c4685414dd2f291b9ea52afa6f07468c8"
432dependencies = [
433 "log",
434 "plain",
435 "scroll",
436]
437
438[[package]]
428name = "heck" 439name = "heck"
429version = "0.3.1" 440version = "0.3.1"
430source = "registry+https://github.com/rust-lang/crates.io-index" 441source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -587,6 +598,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
587checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" 598checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
588 599
589[[package]] 600[[package]]
601name = "libloading"
602version = "0.6.0"
603source = "registry+https://github.com/rust-lang/crates.io-index"
604checksum = "2c979a19ffb457f0273965c333053f3d586bf759bf7b683fbebc37f9a9ebedc4"
605dependencies = [
606 "winapi 0.3.8",
607]
608
609[[package]]
590name = "linked-hash-map" 610name = "linked-hash-map"
591version = "0.5.2" 611version = "0.5.2"
592source = "registry+https://github.com/rust-lang/crates.io-index" 612source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -594,9 +614,9 @@ checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
594 614
595[[package]] 615[[package]]
596name = "lock_api" 616name = "lock_api"
597version = "0.3.3" 617version = "0.3.4"
598source = "registry+https://github.com/rust-lang/crates.io-index" 618source = "registry+https://github.com/rust-lang/crates.io-index"
599checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" 619checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
600dependencies = [ 620dependencies = [
601 "scopeguard", 621 "scopeguard",
602] 622]
@@ -759,9 +779,9 @@ checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
759 779
760[[package]] 780[[package]]
761name = "parking_lot" 781name = "parking_lot"
762version = "0.10.0" 782version = "0.10.1"
763source = "registry+https://github.com/rust-lang/crates.io-index" 783source = "registry+https://github.com/rust-lang/crates.io-index"
764checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" 784checksum = "6fdfcb5f20930a79e326f7ec992a9fdb5b7bd809254b1e735bdd5a99f78bee0d"
765dependencies = [ 785dependencies = [
766 "lock_api", 786 "lock_api",
767 "parking_lot_core", 787 "parking_lot_core",
@@ -769,9 +789,9 @@ dependencies = [
769 789
770[[package]] 790[[package]]
771name = "parking_lot_core" 791name = "parking_lot_core"
772version = "0.7.0" 792version = "0.7.1"
773source = "registry+https://github.com/rust-lang/crates.io-index" 793source = "registry+https://github.com/rust-lang/crates.io-index"
774checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" 794checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
775dependencies = [ 795dependencies = [
776 "cfg-if", 796 "cfg-if",
777 "cloudabi", 797 "cloudabi",
@@ -826,6 +846,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
826checksum = "3ad1f1b834a05d42dae330066e9699a173b28185b3bdc3dbf14ca239585de8cc" 846checksum = "3ad1f1b834a05d42dae330066e9699a173b28185b3bdc3dbf14ca239585de8cc"
827 847
828[[package]] 848[[package]]
849name = "plain"
850version = "0.2.3"
851source = "registry+https://github.com/rust-lang/crates.io-index"
852checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
853
854[[package]]
829name = "ppv-lite86" 855name = "ppv-lite86"
830version = "0.2.6" 856version = "0.2.6"
831source = "registry+https://github.com/rust-lang/crates.io-index" 857source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -995,6 +1021,7 @@ dependencies = [
995 "ra_prof", 1021 "ra_prof",
996 "ra_syntax", 1022 "ra_syntax",
997 "rustc-hash", 1023 "rustc-hash",
1024 "scoped-tls",
998 "smallvec", 1025 "smallvec",
999 "stdx", 1026 "stdx",
1000 "test_utils", 1027 "test_utils",
@@ -1081,10 +1108,13 @@ version = "0.1.0"
1081dependencies = [ 1108dependencies = [
1082 "cargo_metadata", 1109 "cargo_metadata",
1083 "difference", 1110 "difference",
1111 "goblin",
1112 "libloading",
1084 "ra_mbe", 1113 "ra_mbe",
1085 "ra_proc_macro", 1114 "ra_proc_macro",
1086 "ra_tt", 1115 "ra_tt",
1087 "serde_derive", 1116 "serde_derive",
1117 "test_utils",
1088] 1118]
1089 1119
1090[[package]] 1120[[package]]
@@ -1391,12 +1421,38 @@ dependencies = [
1391] 1421]
1392 1422
1393[[package]] 1423[[package]]
1424name = "scoped-tls"
1425version = "1.0.0"
1426source = "registry+https://github.com/rust-lang/crates.io-index"
1427checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
1428
1429[[package]]
1394name = "scopeguard" 1430name = "scopeguard"
1395version = "1.1.0" 1431version = "1.1.0"
1396source = "registry+https://github.com/rust-lang/crates.io-index" 1432source = "registry+https://github.com/rust-lang/crates.io-index"
1397checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1433checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1398 1434
1399[[package]] 1435[[package]]
1436name = "scroll"
1437version = "0.10.1"
1438source = "registry+https://github.com/rust-lang/crates.io-index"
1439checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1"
1440dependencies = [
1441 "scroll_derive",
1442]
1443
1444[[package]]
1445name = "scroll_derive"
1446version = "0.10.1"
1447source = "registry+https://github.com/rust-lang/crates.io-index"
1448checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
1449dependencies = [
1450 "proc-macro2",
1451 "quote",
1452 "syn",
1453]
1454
1455[[package]]
1400name = "semver" 1456name = "semver"
1401version = "0.9.0" 1457version = "0.9.0"
1402source = "registry+https://github.com/rust-lang/crates.io-index" 1458source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1474,9 +1530,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1474 1530
1475[[package]] 1531[[package]]
1476name = "smallvec" 1532name = "smallvec"
1477version = "1.2.0" 1533version = "1.3.0"
1478source = "registry+https://github.com/rust-lang/crates.io-index" 1534source = "registry+https://github.com/rust-lang/crates.io-index"
1479checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" 1535checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
1480 1536
1481[[package]] 1537[[package]]
1482name = "smol_str" 1538name = "smol_str"
@@ -1524,9 +1580,9 @@ dependencies = [
1524 1580
1525[[package]] 1581[[package]]
1526name = "termios" 1582name = "termios"
1527version = "0.3.1" 1583version = "0.3.2"
1528source = "registry+https://github.com/rust-lang/crates.io-index" 1584source = "registry+https://github.com/rust-lang/crates.io-index"
1529checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" 1585checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2"
1530dependencies = [ 1586dependencies = [
1531 "libc", 1587 "libc",
1532] 1588]
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
index 6dc049715..b63b4d81a 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -180,7 +180,7 @@ trait Trait<T> {
180} 180}
181 181
182impl Trait<u32> for () { 182impl Trait<u32> for () {
183 fn foo(&self) -> u32 { unimplemented!() } 183 fn foo(&self) -> u32 { todo!() }
184 184
185} 185}
186"#####, 186"#####,
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index e7dcfb44e..d86d804b2 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -1,6 +1,6 @@
1use hir::HirDisplay; 1use hir::HirDisplay;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode, AstToken, LetStmt, NameOwner, TypeAscriptionOwner}, 3 ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
4 TextRange, 4 TextRange,
5}; 5};
6 6
@@ -35,7 +35,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
35 let name = pat.name()?; 35 let name = pat.name()?;
36 let name_range = name.syntax().text_range(); 36 let name_range = name.syntax().text_range();
37 let stmt_range = stmt.syntax().text_range(); 37 let stmt_range = stmt.syntax().text_range();
38 let eq_range = stmt.eq_token()?.syntax().text_range(); 38 let eq_range = stmt.eq_token()?.text_range();
39 // Assist should only be applicable if cursor is between 'let' and '=' 39 // Assist should only be applicable if cursor is between 'let' and '='
40 let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); 40 let let_range = TextRange::from_to(stmt_range.start(), eq_range.start());
41 let cursor_in_range = ctx.frange.range.is_subrange(&let_range); 41 let cursor_in_range = ctx.frange.range.is_subrange(&let_range);
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs
index 26dfed237..6622eadb2 100644
--- a/crates/ra_assists/src/handlers/add_impl.rs
+++ b/crates/ra_assists/src/handlers/add_impl.rs
@@ -1,5 +1,5 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner}, 2 ast::{self, AstNode, NameOwner, TypeParamsOwner},
3 TextUnit, 3 TextUnit,
4}; 4};
5use stdx::{format_to, SepBy}; 5use stdx::{format_to, SepBy};
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index 722f207e2..2d6d44980 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -40,7 +40,7 @@ enum AddMissingImplMembersMode {
40// } 40// }
41// 41//
42// impl Trait<u32> for () { 42// impl Trait<u32> for () {
43// fn foo(&self) -> u32 { unimplemented!() } 43// fn foo(&self) -> u32 { todo!() }
44// 44//
45// } 45// }
46// ``` 46// ```
@@ -165,7 +165,7 @@ fn add_missing_impl_members_inner(
165 165
166fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 166fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
167 if fn_def.body().is_none() { 167 if fn_def.body().is_none() {
168 fn_def.with_body(make::block_from_expr(make::expr_unimplemented())) 168 fn_def.with_body(make::block_from_expr(make::expr_todo()))
169 } else { 169 } else {
170 fn_def 170 fn_def
171 } 171 }
@@ -215,8 +215,8 @@ impl Foo for S {
215 fn bar(&self) {} 215 fn bar(&self) {}
216 <|>type Output; 216 <|>type Output;
217 const CONST: usize = 42; 217 const CONST: usize = 42;
218 fn foo(&self) { unimplemented!() } 218 fn foo(&self) { todo!() }
219 fn baz(&self) { unimplemented!() } 219 fn baz(&self) { todo!() }
220 220
221}", 221}",
222 ); 222 );
@@ -250,7 +250,7 @@ struct S;
250 250
251impl Foo for S { 251impl Foo for S {
252 fn bar(&self) {} 252 fn bar(&self) {}
253 <|>fn foo(&self) { unimplemented!() } 253 <|>fn foo(&self) { todo!() }
254 254
255}", 255}",
256 ); 256 );
@@ -268,7 +268,7 @@ impl Foo for S { <|> }",
268trait Foo { fn foo(&self); } 268trait Foo { fn foo(&self); }
269struct S; 269struct S;
270impl Foo for S { 270impl Foo for S {
271 <|>fn foo(&self) { unimplemented!() } 271 <|>fn foo(&self) { todo!() }
272}", 272}",
273 ); 273 );
274 } 274 }
@@ -285,7 +285,7 @@ impl Foo<u32> for S { <|> }",
285trait Foo<T> { fn foo(&self, t: T) -> &T; } 285trait Foo<T> { fn foo(&self, t: T) -> &T; }
286struct S; 286struct S;
287impl Foo<u32> for S { 287impl Foo<u32> for S {
288 <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() } 288 <|>fn foo(&self, t: u32) -> &u32 { todo!() }
289}", 289}",
290 ); 290 );
291 } 291 }
@@ -302,7 +302,7 @@ impl<U> Foo<U> for S { <|> }",
302trait Foo<T> { fn foo(&self, t: T) -> &T; } 302trait Foo<T> { fn foo(&self, t: T) -> &T; }
303struct S; 303struct S;
304impl<U> Foo<U> for S { 304impl<U> Foo<U> for S {
305 <|>fn foo(&self, t: U) -> &U { unimplemented!() } 305 <|>fn foo(&self, t: U) -> &U { todo!() }
306}", 306}",
307 ); 307 );
308 } 308 }
@@ -319,7 +319,7 @@ impl Foo for S {}<|>",
319trait Foo { fn foo(&self); } 319trait Foo { fn foo(&self); }
320struct S; 320struct S;
321impl Foo for S { 321impl Foo for S {
322 <|>fn foo(&self) { unimplemented!() } 322 <|>fn foo(&self) { todo!() }
323}", 323}",
324 ) 324 )
325 } 325 }
@@ -342,7 +342,7 @@ mod foo {
342} 342}
343struct S; 343struct S;
344impl foo::Foo for S { 344impl foo::Foo for S {
345 <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } 345 <|>fn foo(&self, bar: foo::Bar) { todo!() }
346}", 346}",
347 ); 347 );
348 } 348 }
@@ -365,7 +365,7 @@ mod foo {
365} 365}
366struct S; 366struct S;
367impl foo::Foo for S { 367impl foo::Foo for S {
368 <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } 368 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() }
369}", 369}",
370 ); 370 );
371 } 371 }
@@ -388,7 +388,7 @@ mod foo {
388} 388}
389struct S; 389struct S;
390impl foo::Foo<u32> for S { 390impl foo::Foo<u32> for S {
391 <|>fn foo(&self, bar: foo::Bar<u32>) { unimplemented!() } 391 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() }
392}", 392}",
393 ); 393 );
394 } 394 }
@@ -414,7 +414,7 @@ mod foo {
414struct Param; 414struct Param;
415struct S; 415struct S;
416impl foo::Foo<Param> for S { 416impl foo::Foo<Param> for S {
417 <|>fn foo(&self, bar: Param) { unimplemented!() } 417 <|>fn foo(&self, bar: Param) { todo!() }
418}", 418}",
419 ); 419 );
420 } 420 }
@@ -439,7 +439,7 @@ mod foo {
439} 439}
440struct S; 440struct S;
441impl foo::Foo for S { 441impl foo::Foo for S {
442 <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { unimplemented!() } 442 <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { todo!() }
443}", 443}",
444 ); 444 );
445 } 445 }
@@ -464,7 +464,7 @@ mod foo {
464} 464}
465struct S; 465struct S;
466impl foo::Foo for S { 466impl foo::Foo for S {
467 <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { unimplemented!() } 467 <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { todo!() }
468}", 468}",
469 ); 469 );
470 } 470 }
@@ -487,7 +487,7 @@ mod foo {
487} 487}
488struct S; 488struct S;
489impl foo::Foo for S { 489impl foo::Foo for S {
490 <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { unimplemented!() } 490 <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { todo!() }
491}", 491}",
492 ); 492 );
493 } 493 }
@@ -544,7 +544,7 @@ trait Foo {
544struct S; 544struct S;
545impl Foo for S { 545impl Foo for S {
546 <|>type Output; 546 <|>type Output;
547 fn foo(&self) { unimplemented!() } 547 fn foo(&self) { todo!() }
548}"#, 548}"#,
549 ) 549 )
550 } 550 }
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs
index 30360af94..240b19fa3 100644
--- a/crates/ra_assists/src/handlers/add_new.rs
+++ b/crates/ra_assists/src/handlers/add_new.rs
@@ -1,8 +1,7 @@
1use hir::Adt; 1use hir::Adt;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{ 3 ast::{
4 self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, 4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
5 VisibilityOwner,
6 }, 5 },
7 TextUnit, T, 6 TextUnit, T,
8}; 7};
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs
index ab6bdf6bb..8d0f7e922 100644
--- a/crates/ra_assists/src/handlers/introduce_variable.rs
+++ b/crates/ra_assists/src/handlers/introduce_variable.rs
@@ -61,7 +61,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
61 }; 61 };
62 if is_full_stmt { 62 if is_full_stmt {
63 tested_by!(test_introduce_var_expr_stmt); 63 tested_by!(test_introduce_var_expr_stmt);
64 if full_stmt.unwrap().semi_token().is_none() { 64 if full_stmt.unwrap().semicolon_token().is_none() {
65 buf.push_str(";"); 65 buf.push_str(";");
66 } 66 }
67 edit.replace(expr.syntax().text_range(), buf); 67 edit.replace(expr.syntax().text_range(), buf);
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 936d50ab4..0958f52f1 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{neighbor, SyntaxRewriter}, 4 algo::{neighbor, SyntaxRewriter},
5 ast::{self, edit::AstNodeEdit, make}, 5 ast::{self, edit::AstNodeEdit, make},
6 AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T, 6 AstNode, Direction, InsertPosition, SyntaxElement, T,
7}; 7};
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{Assist, AssistCtx, AssistId};
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']), 82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
83 ); 83 );
84 let use_tree_list = lhs.use_tree_list()?; 84 let use_tree_list = lhs.use_tree_list()?;
85 let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.syntax().clone().into()); 85 let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.into());
86 let use_tree_list = use_tree_list.insert_children(pos, to_insert); 86 let use_tree_list = use_tree_list.insert_children(pos, to_insert);
87 Some(lhs.with_use_tree_list(use_tree_list)) 87 Some(lhs.with_use_tree_list(use_tree_list))
88} 88}
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs
index 93f26f51a..0f26884dc 100644
--- a/crates/ra_assists/src/handlers/move_bounds.rs
+++ b/crates/ra_assists/src/handlers/move_bounds.rs
@@ -2,6 +2,7 @@ use ra_syntax::{
2 ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, 2 ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner},
3 match_ast, 3 match_ast,
4 SyntaxKind::*, 4 SyntaxKind::*,
5 T,
5}; 6};
6 7
7use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
@@ -42,7 +43,7 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
42 ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), 43 ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(),
43 ast::StructDef(it) => { 44 ast::StructDef(it) => {
44 it.syntax().children_with_tokens() 45 it.syntax().children_with_tokens()
45 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == SEMI)? 46 .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])?
46 }, 47 },
47 _ => return None 48 _ => return None
48 } 49 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 45631f8fd..58ae6ce41 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -139,7 +139,7 @@ impl SourceAnalyzer {
139 &self, 139 &self,
140 db: &dyn HirDatabase, 140 db: &dyn HirDatabase,
141 field: &ast::FieldExpr, 141 field: &ast::FieldExpr,
142 ) -> Option<crate::StructField> { 142 ) -> Option<StructField> {
143 let expr_id = self.expr_id(db, &field.clone().into())?; 143 let expr_id = self.expr_id(db, &field.clone().into())?;
144 self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into()) 144 self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
145 } 145 }
@@ -148,21 +148,19 @@ impl SourceAnalyzer {
148 &self, 148 &self,
149 db: &dyn HirDatabase, 149 db: &dyn HirDatabase,
150 field: &ast::RecordField, 150 field: &ast::RecordField,
151 ) -> Option<(crate::StructField, Option<Local>)> { 151 ) -> Option<(StructField, Option<Local>)> {
152 let (expr_id, local) = match field.expr() { 152 let expr = field.expr()?;
153 Some(it) => (self.expr_id(db, &it)?, None), 153 let expr_id = self.expr_id(db, &expr)?;
154 None => { 154 let local = if field.name_ref().is_some() {
155 let src = InFile { file_id: self.file_id, value: field }; 155 None
156 let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?; 156 } else {
157 let local_name = field.name_ref()?.as_name(); 157 let local_name = field.field_name()?.as_name();
158 let path = ModPath::from_segments(PathKind::Plain, once(local_name)); 158 let path = ModPath::from_segments(PathKind::Plain, once(local_name));
159 let local = match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { 159 match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
160 Some(ValueNs::LocalBinding(pat_id)) => { 160 Some(ValueNs::LocalBinding(pat_id)) => {
161 Some(Local { pat_id, parent: self.resolver.body_owner()? }) 161 Some(Local { pat_id, parent: self.resolver.body_owner()? })
162 } 162 }
163 _ => None, 163 _ => None,
164 };
165 (expr_id, local)
166 } 164 }
167 }; 165 };
168 let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?; 166 let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?;
@@ -255,7 +253,7 @@ impl SourceAnalyzer {
255 _ => return None, 253 _ => return None,
256 }; 254 };
257 255
258 let (variant, missing_fields) = 256 let (variant, missing_fields, _exhaustive) =
259 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; 257 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
260 let res = self.missing_fields(db, krate, substs, variant, missing_fields); 258 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
261 Some(res) 259 Some(res)
@@ -319,8 +317,7 @@ fn scope_for_offset(
319 if source.file_id != offset.file_id { 317 if source.file_id != offset.file_id {
320 return None; 318 return None;
321 } 319 }
322 let syntax_node_ptr = 320 let syntax_node_ptr = source.value.syntax_node_ptr();
323 source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
324 Some((syntax_node_ptr, scope)) 321 Some((syntax_node_ptr, scope))
325 }) 322 })
326 // find containing scope 323 // find containing scope
@@ -399,8 +396,7 @@ fn adjust(
399 if source.file_id != file_id { 396 if source.file_id != file_id {
400 return None; 397 return None;
401 } 398 }
402 let syntax_node_ptr = 399 let syntax_node_ptr = source.value.syntax_node_ptr();
403 source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
404 Some((syntax_node_ptr, scope)) 400 Some((syntax_node_ptr, scope))
405 }) 401 })
406 .map(|(ptr, scope)| (ptr.range(), scope)) 402 .map(|(ptr, scope)| (ptr.range(), scope))
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index be4b0accb..7c0d93691 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -4,7 +4,6 @@ use std::sync::Arc;
4 4
5use either::Either; 5use either::Either;
6use hir_expand::{ 6use hir_expand::{
7 hygiene::Hygiene,
8 name::{AsName, Name}, 7 name::{AsName, Name},
9 InFile, 8 InFile,
10}; 9};
@@ -13,7 +12,7 @@ use ra_prof::profile;
13use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
14 13
15use crate::{ 14use crate::{
16 attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
17 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
18 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
19}; 18};
@@ -125,8 +124,9 @@ fn lower_enum(
125 124
126impl VariantData { 125impl VariantData {
127 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { 126 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
127 let mut expander = CfgExpander::new(db, flavor.file_id, module_id.krate);
128 let mut trace = Trace::new_for_arena(); 128 let mut trace = Trace::new_for_arena();
129 match lower_struct(db, &mut trace, &flavor, module_id) { 129 match lower_struct(db, &mut expander, &mut trace, &flavor) {
130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()), 130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
131 StructKind::Record => VariantData::Record(trace.into_arena()), 131 StructKind::Record => VariantData::Record(trace.into_arena()),
132 StructKind::Unit => VariantData::Unit, 132 StructKind::Unit => VariantData::Unit,
@@ -178,8 +178,9 @@ impl HasChildSource for VariantId {
178 it.lookup(db).container.module(db), 178 it.lookup(db).container.module(db),
179 ), 179 ),
180 }; 180 };
181 let mut expander = CfgExpander::new(db, src.file_id, module_id.krate);
181 let mut trace = Trace::new_for_map(); 182 let mut trace = Trace::new_for_map();
182 lower_struct(db, &mut trace, &src, module_id); 183 lower_struct(db, &mut expander, &mut trace, &src);
183 src.with_value(trace.into_map()) 184 src.with_value(trace.into_map())
184 } 185 }
185} 186}
@@ -193,16 +194,15 @@ pub enum StructKind {
193 194
194fn lower_struct( 195fn lower_struct(
195 db: &dyn DefDatabase, 196 db: &dyn DefDatabase,
197 expander: &mut CfgExpander,
196 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 198 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
197 ast: &InFile<ast::StructKind>, 199 ast: &InFile<ast::StructKind>,
198 module_id: ModuleId,
199) -> StructKind { 200) -> StructKind {
200 let crate_graph = db.crate_graph();
201 match &ast.value { 201 match &ast.value {
202 ast::StructKind::Tuple(fl) => { 202 ast::StructKind::Tuple(fl) => {
203 for (i, fd) in fl.fields().enumerate() { 203 for (i, fd) in fl.fields().enumerate() {
204 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); 204 let attrs = expander.parse_attrs(&fd);
205 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { 205 if !expander.is_cfg_enabled(&attrs) {
206 continue; 206 continue;
207 } 207 }
208 208
@@ -219,8 +219,8 @@ fn lower_struct(
219 } 219 }
220 ast::StructKind::Record(fl) => { 220 ast::StructKind::Record(fl) => {
221 for fd in fl.fields() { 221 for fd in fl.fields() {
222 let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); 222 let attrs = expander.parse_attrs(&fd);
223 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { 223 if !expander.is_cfg_enabled(&attrs) {
224 continue; 224 continue;
225 } 225 }
226 226
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 7b0c506b1..2f2e3e5ba 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -93,6 +93,7 @@ impl Attrs {
93 } 93 }
94 94
95 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { 95 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
96 // FIXME: handle cfg_attr :-)
96 self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) 97 self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
97 } 98 }
98} 99}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 5f9d53ecb..eafaf48c1 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -9,11 +9,14 @@ use drop_bomb::DropBomb;
9use either::Either; 9use either::Either;
10use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; 10use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId};
11use ra_arena::{map::ArenaMap, Arena}; 11use ra_arena::{map::ArenaMap, Arena};
12use ra_cfg::CfgOptions;
13use ra_db::CrateId;
12use ra_prof::profile; 14use ra_prof::profile;
13use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
14use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
15 17
16use crate::{ 18use crate::{
19 attr::Attrs,
17 db::DefDatabase, 20 db::DefDatabase,
18 expr::{Expr, ExprId, Pat, PatId}, 21 expr::{Expr, ExprId, Pat, PatId},
19 item_scope::BuiltinShadowMode, 22 item_scope::BuiltinShadowMode,
@@ -24,25 +27,59 @@ use crate::{
24 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 27 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
25}; 28};
26 29
30/// A subser of Exander that only deals with cfg attributes. We only need it to
31/// avoid cyclic queries in crate def map during enum processing.
32pub(crate) struct CfgExpander {
33 cfg_options: CfgOptions,
34 hygiene: Hygiene,
35}
36
27pub(crate) struct Expander { 37pub(crate) struct Expander {
38 cfg_expander: CfgExpander,
28 crate_def_map: Arc<CrateDefMap>, 39 crate_def_map: Arc<CrateDefMap>,
29 current_file_id: HirFileId, 40 current_file_id: HirFileId,
30 hygiene: Hygiene,
31 ast_id_map: Arc<AstIdMap>, 41 ast_id_map: Arc<AstIdMap>,
32 module: ModuleId, 42 module: ModuleId,
33 recursive_limit: usize, 43 recursive_limit: usize,
34} 44}
35 45
46impl CfgExpander {
47 pub(crate) fn new(
48 db: &dyn DefDatabase,
49 current_file_id: HirFileId,
50 krate: CrateId,
51 ) -> CfgExpander {
52 let hygiene = Hygiene::new(db.upcast(), current_file_id);
53 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
54 CfgExpander { cfg_options, hygiene }
55 }
56
57 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
58 Attrs::new(owner, &self.hygiene)
59 }
60
61 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
62 attrs.is_cfg_enabled(&self.cfg_options)
63 }
64}
65
36impl Expander { 66impl Expander {
37 pub(crate) fn new( 67 pub(crate) fn new(
38 db: &dyn DefDatabase, 68 db: &dyn DefDatabase,
39 current_file_id: HirFileId, 69 current_file_id: HirFileId,
40 module: ModuleId, 70 module: ModuleId,
41 ) -> Expander { 71 ) -> Expander {
72 let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
42 let crate_def_map = db.crate_def_map(module.krate); 73 let crate_def_map = db.crate_def_map(module.krate);
43 let hygiene = Hygiene::new(db.upcast(), current_file_id);
44 let ast_id_map = db.ast_id_map(current_file_id); 74 let ast_id_map = db.ast_id_map(current_file_id);
45 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module, recursive_limit: 0 } 75 Expander {
76 cfg_expander,
77 crate_def_map,
78 current_file_id,
79 ast_id_map,
80 module,
81 recursive_limit: 0,
82 }
46 } 83 }
47 84
48 pub(crate) fn enter_expand<T: ast::AstNode>( 85 pub(crate) fn enter_expand<T: ast::AstNode>(
@@ -75,7 +112,7 @@ impl Expander {
75 ast_id_map: mem::take(&mut self.ast_id_map), 112 ast_id_map: mem::take(&mut self.ast_id_map),
76 bomb: DropBomb::new("expansion mark dropped"), 113 bomb: DropBomb::new("expansion mark dropped"),
77 }; 114 };
78 self.hygiene = Hygiene::new(db.upcast(), file_id); 115 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
79 self.current_file_id = file_id; 116 self.current_file_id = file_id;
80 self.ast_id_map = db.ast_id_map(file_id); 117 self.ast_id_map = db.ast_id_map(file_id);
81 self.recursive_limit += 1; 118 self.recursive_limit += 1;
@@ -91,7 +128,7 @@ impl Expander {
91 } 128 }
92 129
93 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { 130 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
94 self.hygiene = Hygiene::new(db.upcast(), mark.file_id); 131 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
95 self.current_file_id = mark.file_id; 132 self.current_file_id = mark.file_id;
96 self.ast_id_map = mem::take(&mut mark.ast_id_map); 133 self.ast_id_map = mem::take(&mut mark.ast_id_map);
97 self.recursive_limit -= 1; 134 self.recursive_limit -= 1;
@@ -102,8 +139,16 @@ impl Expander {
102 InFile { file_id: self.current_file_id, value } 139 InFile { file_id: self.current_file_id, value }
103 } 140 }
104 141
142 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
143 self.cfg_expander.parse_attrs(owner)
144 }
145
146 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
147 self.cfg_expander.is_cfg_enabled(attrs)
148 }
149
105 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 150 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
106 Path::from_src(path, &self.hygiene) 151 Path::from_src(path, &self.cfg_expander.hygiene)
107 } 152 }
108 153
109 fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { 154 fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
@@ -142,7 +187,7 @@ pub struct Body {
142 pub item_scope: ItemScope, 187 pub item_scope: ItemScope,
143} 188}
144 189
145pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 190pub type ExprPtr = AstPtr<ast::Expr>;
146pub type ExprSource = InFile<ExprPtr>; 191pub type ExprSource = InFile<ExprPtr>;
147 192
148pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 193pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
@@ -236,11 +281,11 @@ impl Index<PatId> for Body {
236 281
237impl BodySourceMap { 282impl BodySourceMap {
238 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { 283 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
239 self.expr_map_back[expr] 284 self.expr_map_back[expr].clone()
240 } 285 }
241 286
242 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { 287 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
243 let src = node.map(|it| Either::Left(AstPtr::new(it))); 288 let src = node.map(|it| AstPtr::new(it));
244 self.expr_map.get(&src).cloned() 289 self.expr_map.get(&src).cloned()
245 } 290 }
246 291
@@ -249,13 +294,8 @@ impl BodySourceMap {
249 self.expansions.get(&src).cloned() 294 self.expansions.get(&src).cloned()
250 } 295 }
251 296
252 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
253 let src = node.map(|it| Either::Right(AstPtr::new(it)));
254 self.expr_map.get(&src).cloned()
255 }
256
257 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { 297 pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
258 self.pat_map_back[pat] 298 self.pat_map_back[pat].clone()
259 } 299 }
260 300
261 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { 301 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
@@ -264,6 +304,6 @@ impl BodySourceMap {
264 } 304 }
265 305
266 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { 306 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
267 self.field_map[&(expr, field)] 307 self.field_map[&(expr, field)].clone()
268 } 308 }
269} 309}
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e1b08d48f..c057dc8f2 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,9 +2,7 @@
2//! representation. 2//! representation.
3 3
4use either::Either; 4use either::Either;
5
6use hir_expand::{ 5use hir_expand::{
7 hygiene::Hygiene,
8 name::{name, AsName, Name}, 6 name::{name, AsName, Name},
9 MacroDefId, MacroDefKind, 7 MacroDefId, MacroDefKind,
10}; 8};
@@ -18,10 +16,8 @@ use ra_syntax::{
18}; 16};
19use test_utils::tested_by; 17use test_utils::tested_by;
20 18
21use super::{ExprSource, PatSource};
22use crate::{ 19use crate::{
23 adt::StructKind, 20 adt::StructKind,
24 attr::Attrs,
25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 21 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
26 builtin_type::{BuiltinFloat, BuiltinInt}, 22 builtin_type::{BuiltinFloat, BuiltinInt},
27 db::DefDatabase, 23 db::DefDatabase,
@@ -31,12 +27,13 @@ use crate::{
31 }, 27 },
32 item_scope::BuiltinShadowMode, 28 item_scope::BuiltinShadowMode,
33 path::GenericArgs, 29 path::GenericArgs,
34 path::Path,
35 type_ref::{Mutability, TypeRef}, 30 type_ref::{Mutability, TypeRef},
36 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern, 31 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
37 ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 32 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
38}; 33};
39 34
35use super::{ExprSource, PatSource};
36
40pub(super) fn lower( 37pub(super) fn lower(
41 db: &dyn DefDatabase, 38 db: &dyn DefDatabase,
42 def: DefWithBodyId, 39 def: DefWithBodyId,
@@ -104,9 +101,8 @@ impl ExprCollector<'_> {
104 } 101 }
105 102
106 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 103 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
107 let ptr = Either::Left(ptr);
108 let src = self.expander.to_source(ptr); 104 let src = self.expander.to_source(ptr);
109 let id = self.make_expr(expr, Ok(src)); 105 let id = self.make_expr(expr, Ok(src.clone()));
110 self.source_map.expr_map.insert(src, id); 106 self.source_map.expr_map.insert(src, id);
111 id 107 id
112 } 108 }
@@ -115,13 +111,6 @@ impl ExprCollector<'_> {
115 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { 111 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
116 self.make_expr(expr, Err(SyntheticSyntax)) 112 self.make_expr(expr, Err(SyntheticSyntax))
117 } 113 }
118 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
119 let ptr = Either::Right(ptr);
120 let src = self.expander.to_source(ptr);
121 let id = self.make_expr(expr, Ok(src));
122 self.source_map.expr_map.insert(src, id);
123 id
124 }
125 fn empty_block(&mut self) -> ExprId { 114 fn empty_block(&mut self) -> ExprId {
126 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 115 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None })
127 } 116 }
@@ -136,7 +125,7 @@ impl ExprCollector<'_> {
136 125
137 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 126 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
138 let src = self.expander.to_source(ptr); 127 let src = self.expander.to_source(ptr);
139 let id = self.make_pat(pat, Ok(src)); 128 let id = self.make_pat(pat, Ok(src.clone()));
140 self.source_map.pat_map.insert(src, id); 129 self.source_map.pat_map.insert(src, id);
141 id 130 id
142 } 131 }
@@ -291,7 +280,7 @@ impl ExprCollector<'_> {
291 ast::Expr::ParenExpr(e) => { 280 ast::Expr::ParenExpr(e) => {
292 let inner = self.collect_expr_opt(e.expr()); 281 let inner = self.collect_expr_opt(e.expr());
293 // make the paren expr point to the inner expression as well 282 // make the paren expr point to the inner expression as well
294 let src = self.expander.to_source(Either::Left(syntax_ptr)); 283 let src = self.expander.to_source(syntax_ptr);
295 self.source_map.expr_map.insert(src, inner); 284 self.source_map.expr_map.insert(src, inner);
296 inner 285 inner
297 } 286 }
@@ -300,7 +289,6 @@ impl ExprCollector<'_> {
300 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 289 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
301 } 290 }
302 ast::Expr::RecordLit(e) => { 291 ast::Expr::RecordLit(e) => {
303 let crate_graph = self.db.crate_graph();
304 let path = e.path().and_then(|path| self.expander.parse_path(path)); 292 let path = e.path().and_then(|path| self.expander.parse_path(path));
305 let mut field_ptrs = Vec::new(); 293 let mut field_ptrs = Vec::new();
306 let record_lit = if let Some(nfl) = e.record_field_list() { 294 let record_lit = if let Some(nfl) = e.record_field_list() {
@@ -308,31 +296,17 @@ impl ExprCollector<'_> {
308 .fields() 296 .fields()
309 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 297 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
310 .filter_map(|field| { 298 .filter_map(|field| {
311 let module_id = ContainerId::DefWithBodyId(self.def).module(self.db); 299 let attrs = self.expander.parse_attrs(&field);
312 let attrs = Attrs::new( 300 if !self.expander.is_cfg_enabled(&attrs) {
313 &field,
314 &Hygiene::new(self.db.upcast(), self.expander.current_file_id),
315 );
316
317 if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
318 return None; 301 return None;
319 } 302 }
303 let name = field.field_name()?.as_name();
320 304
321 Some(RecordLitField { 305 Some(RecordLitField {
322 name: field 306 name,
323 .name_ref() 307 expr: match field.expr() {
324 .map(|nr| nr.as_name()) 308 Some(e) => self.collect_expr(e),
325 .unwrap_or_else(Name::missing), 309 None => self.missing_expr(),
326 expr: if let Some(e) = field.expr() {
327 self.collect_expr(e)
328 } else if let Some(nr) = field.name_ref() {
329 // field shorthand
330 self.alloc_expr_field_shorthand(
331 Expr::Path(Path::from_name_ref(&nr)),
332 AstPtr::new(&field),
333 )
334 } else {
335 self.missing_expr()
336 }, 310 },
337 }) 311 })
338 }) 312 })
@@ -668,7 +642,9 @@ impl ExprCollector<'_> {
668 }); 642 });
669 fields.extend(iter); 643 fields.extend(iter);
670 644
671 Pat::Record { path, args: fields } 645 let ellipsis = record_field_pat_list.dotdot_token().is_some();
646
647 Pat::Record { path, args: fields, ellipsis }
672 } 648 }
673 ast::Pat::SlicePat(p) => { 649 ast::Pat::SlicePat(p) => {
674 let SlicePatComponents { prefix, slice, suffix } = p.components(); 650 let SlicePatComponents { prefix, slice, suffix } = p.components();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b8fbf0ed4..56a20c5bd 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -20,7 +20,7 @@ use crate::{
20 type_ref::{Mutability, TypeBound, TypeRef}, 20 type_ref::{Mutability, TypeBound, TypeRef},
21 visibility::RawVisibility, 21 visibility::RawVisibility,
22 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 22 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
23 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 23 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
24}; 24};
25 25
26#[derive(Debug, Clone, PartialEq, Eq)] 26#[derive(Debug, Clone, PartialEq, Eq)]
@@ -218,10 +218,17 @@ impl ImplData {
218 let mut items = Vec::new(); 218 let mut items = Vec::new();
219 219
220 if let Some(item_list) = src.value.item_list() { 220 if let Some(item_list) = src.value.item_list() {
221 items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); 221 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
222 items.extend(collect_impl_items(
223 db,
224 &mut expander,
225 item_list.impl_items(),
226 src.file_id,
227 id,
228 ));
222 items.extend(collect_impl_items_in_macros( 229 items.extend(collect_impl_items_in_macros(
223 db, 230 db,
224 module_id, 231 &mut expander,
225 &src.with_value(item_list), 232 &src.with_value(item_list),
226 id, 233 id,
227 )); 234 ));
@@ -268,18 +275,17 @@ impl ConstData {
268 275
269fn collect_impl_items_in_macros( 276fn collect_impl_items_in_macros(
270 db: &dyn DefDatabase, 277 db: &dyn DefDatabase,
271 module_id: ModuleId, 278 expander: &mut Expander,
272 impl_def: &InFile<ast::ItemList>, 279 impl_def: &InFile<ast::ItemList>,
273 id: ImplId, 280 id: ImplId,
274) -> Vec<AssocItemId> { 281) -> Vec<AssocItemId> {
275 let mut expander = Expander::new(db, impl_def.file_id, module_id);
276 let mut res = Vec::new(); 282 let mut res = Vec::new();
277 283
278 // We set a limit to protect against infinite recursion 284 // We set a limit to protect against infinite recursion
279 let limit = 100; 285 let limit = 100;
280 286
281 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 287 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
282 res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) 288 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit))
283 } 289 }
284 290
285 res 291 res
@@ -300,6 +306,7 @@ fn collect_impl_items_in_macro(
300 let items: InFile<ast::MacroItems> = expander.to_source(items); 306 let items: InFile<ast::MacroItems> = expander.to_source(items);
301 let mut res = collect_impl_items( 307 let mut res = collect_impl_items(
302 db, 308 db,
309 expander,
303 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 310 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
304 items.file_id, 311 items.file_id,
305 id, 312 id,
@@ -319,32 +326,26 @@ fn collect_impl_items_in_macro(
319 326
320fn collect_impl_items( 327fn collect_impl_items(
321 db: &dyn DefDatabase, 328 db: &dyn DefDatabase,
329 expander: &mut Expander,
322 impl_items: impl Iterator<Item = ImplItem>, 330 impl_items: impl Iterator<Item = ImplItem>,
323 file_id: crate::HirFileId, 331 file_id: crate::HirFileId,
324 id: ImplId, 332 id: ImplId,
325) -> Vec<AssocItemId> { 333) -> Vec<AssocItemId> {
326 let items = db.ast_id_map(file_id); 334 let items = db.ast_id_map(file_id);
327 let crate_graph = db.crate_graph();
328 let module_id = id.lookup(db).container.module(db);
329 335
330 impl_items 336 impl_items
331 .filter_map(|item_node| match item_node { 337 .filter_map(|item_node| match item_node {
332 ast::ImplItem::FnDef(it) => { 338 ast::ImplItem::FnDef(it) => {
339 let attrs = expander.parse_attrs(&it);
340 if !expander.is_cfg_enabled(&attrs) {
341 return None;
342 }
333 let def = FunctionLoc { 343 let def = FunctionLoc {
334 container: AssocContainerId::ImplId(id), 344 container: AssocContainerId::ImplId(id),
335 ast_id: AstId::new(file_id, items.ast_id(&it)), 345 ast_id: AstId::new(file_id, items.ast_id(&it)),
336 } 346 }
337 .intern(db); 347 .intern(db);
338 348 Some(def.into())
339 if !db
340 .function_data(def)
341 .attrs
342 .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options)
343 {
344 None
345 } else {
346 Some(def.into())
347 }
348 } 349 }
349 ast::ImplItem::ConstDef(it) => { 350 ast::ImplItem::ConstDef(it) => {
350 let def = ConstLoc { 351 let def = ConstLoc {
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 095498429..cfa0f2f76 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> InFile<SyntaxNodePtr> { 22 fn source(&self) -> InFile<SyntaxNodePtr> {
23 InFile { file_id: self.file, value: self.decl.into() } 23 InFile { file_id: self.file, value: self.decl.clone().into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 197bbe9bd..e11bdf3ec 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -376,35 +376,14 @@ pub enum Pat {
376 Wild, 376 Wild,
377 Tuple(Vec<PatId>), 377 Tuple(Vec<PatId>),
378 Or(Vec<PatId>), 378 Or(Vec<PatId>),
379 Record { 379 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool },
380 path: Option<Path>, 380 Range { start: ExprId, end: ExprId },
381 args: Vec<RecordFieldPat>, 381 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
382 // FIXME: 'ellipsis' option
383 },
384 Range {
385 start: ExprId,
386 end: ExprId,
387 },
388 Slice {
389 prefix: Vec<PatId>,
390 slice: Option<PatId>,
391 suffix: Vec<PatId>,
392 },
393 Path(Path), 382 Path(Path),
394 Lit(ExprId), 383 Lit(ExprId),
395 Bind { 384 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
396 mode: BindingAnnotation, 385 TupleStruct { path: Option<Path>, args: Vec<PatId> },
397 name: Name, 386 Ref { pat: PatId, mutability: Mutability },
398 subpat: Option<PatId>,
399 },
400 TupleStruct {
401 path: Option<Path>,
402 args: Vec<PatId>,
403 },
404 Ref {
405 pat: PatId,
406 mutability: Mutability,
407 },
408} 387}
409 388
410impl Pat { 389impl Pat {
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index 01b367278..d96ac8c0a 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -4,6 +4,7 @@
4//! features, such as Fn family of traits. 4//! features, such as Fn family of traits.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use ra_prof::profile;
7use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9 10
@@ -78,6 +79,8 @@ impl LangItems {
78 79
79 /// Salsa query. This will look for lang items in a specific crate. 80 /// Salsa query. This will look for lang items in a specific crate.
80 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> { 81 pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> {
82 let _p = profile("crate_lang_items_query");
83
81 let mut lang_items = LangItems::default(); 84 let mut lang_items = LangItems::default();
82 85
83 let crate_def_map = db.crate_def_map(krate); 86 let crate_def_map = db.crate_def_map(krate);
@@ -95,6 +98,7 @@ impl LangItems {
95 db: &dyn DefDatabase, 98 db: &dyn DefDatabase,
96 module: ModuleId, 99 module: ModuleId,
97 ) -> Option<Arc<LangItems>> { 100 ) -> Option<Arc<LangItems>> {
101 let _p = profile("module_lang_items_query");
98 let mut lang_items = LangItems::default(); 102 let mut lang_items = LangItems::default();
99 lang_items.collect_lang_items(db, module); 103 lang_items.collect_lang_items(db, module);
100 if lang_items.items.is_empty() { 104 if lang_items.items.is_empty() {
@@ -111,6 +115,7 @@ impl LangItems {
111 start_crate: CrateId, 115 start_crate: CrateId,
112 item: SmolStr, 116 item: SmolStr,
113 ) -> Option<LangItemTarget> { 117 ) -> Option<LangItemTarget> {
118 let _p = profile("lang_item_query");
114 let lang_items = db.crate_lang_items(start_crate); 119 let lang_items = db.crate_lang_items(start_crate);
115 let start_crate_target = lang_items.items.get(&item); 120 let start_crate_target = lang_items.items.get(&item);
116 if let Some(target) = start_crate_target { 121 if let Some(target) = start_crate_target {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8fe3f8617..98c74fe25 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -462,6 +462,14 @@ impl DefCollector<'_> {
462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
463 tested_by!(glob_enum); 463 tested_by!(glob_enum);
464 // glob import from enum => just import all the variants 464 // glob import from enum => just import all the variants
465
466 // XXX: urgh, so this works by accident! Here, we look at
467 // the enum data, and, in theory, this might require us to
468 // look back at the crate_def_map, creating a cycle. For
469 // example, `enum E { crate::some_macro!(); }`. Luckely, the
470 // only kind of macro that is allowed inside enum is a
471 // `cfg_macro`, and we don't need to run name resolution for
472 // it, but this is sheer luck!
465 let enum_data = self.db.enum_data(e); 473 let enum_data = self.db.enum_data(e);
466 let resolutions = enum_data 474 let resolutions = enum_data
467 .variants 475 .variants
@@ -977,11 +985,7 @@ impl ModCollector<'_, '_> {
977 } 985 }
978 986
979 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 987 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
980 // FIXME: handle cfg_attr :-) 988 attrs.is_cfg_enabled(self.def_collector.cfg_options)
981 attrs
982 .by_key("cfg")
983 .tt_values()
984 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
985 } 989 }
986} 990}
987 991
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index e72ba52cf..afd538e4a 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -287,7 +287,7 @@ impl RawItemsCollector {
287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); 287 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene);
288 288
289 let ast_id = self.source_ast_id_map.ast_id(&module); 289 let ast_id = self.source_ast_id_map.ast_id(&module);
290 if module.semi_token().is_some() { 290 if module.semicolon_token().is_some() {
291 let item = 291 let item =
292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); 292 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id });
293 self.push_item(current_module, attrs, RawItemKind::Module(item)); 293 self.push_item(current_module, attrs, RawItemKind::Module(item));
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index 496fc6b08..87165ac33 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -32,6 +32,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
32 32
33 use crate::foo::bar::Baz; 33 use crate::foo::bar::Baz;
34 34
35 enum E { A, B }
36 use E::*;
37
35 fn foo() -> i32 { 38 fn foo() -> i32 {
36 1 + 1 39 1 + 1
37 } 40 }
@@ -46,6 +49,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
46 49
47 use crate::foo::bar::Baz; 50 use crate::foo::bar::Baz;
48 51
52 enum E { A, B }
53 use E::*;
54
49 fn foo() -> i32 { 92 } 55 fn foo() -> i32 { 92 }
50 ", 56 ",
51 ); 57 );
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 904080341..91c7b3e09 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -134,11 +134,6 @@ impl Path {
134 lower::lower_path(path, hygiene) 134 lower::lower_path(path, hygiene)
135 } 135 }
136 136
137 /// Converts an `ast::NameRef` into a single-identifier `Path`.
138 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
139 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
140 }
141
142 /// Converts a known mod path to `Path`. 137 /// Converts a known mod path to `Path`.
143 pub(crate) fn from_known_path( 138 pub(crate) fn from_known_path(
144 path: ModPath, 139 path: ModPath,
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs
index 5643ecdce..a3ca302c2 100644
--- a/crates/ra_hir_expand/src/ast_id_map.rs
+++ b/crates/ra_hir_expand/src/ast_id_map.rs
@@ -90,7 +90,7 @@ impl AstIdMap {
90 } 90 }
91 91
92 pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> { 92 pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
93 self.arena[id.raw].cast::<N>().unwrap() 93 self.arena[id.raw].clone().cast::<N>().unwrap()
94 } 94 }
95 95
96 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId { 96 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 9a4a7aa6f..59efc1c31 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -24,6 +24,8 @@ ra_prof = { path = "../ra_prof" }
24ra_syntax = { path = "../ra_syntax" } 24ra_syntax = { path = "../ra_syntax" }
25test_utils = { path = "../test_utils" } 25test_utils = { path = "../test_utils" }
26 26
27scoped-tls = "1"
28
27chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 29chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
28chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 30chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
29chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } 31chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 1462b053f..33da16b48 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -11,7 +11,7 @@ use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
11use ra_prof::profile; 11use ra_prof::profile;
12 12
13use crate::{ 13use crate::{
14 method_resolution::CrateImplDefs, 14 method_resolution::{CrateImplDefs, TyFingerprint},
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty, 16 Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty,
17 TyDefId, TypeCtor, ValueTyDefId, 17 TyDefId, TypeCtor, ValueTyDefId,
@@ -65,7 +65,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
65 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; 65 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
66 66
67 #[salsa::invoke(crate::traits::impls_for_trait_query)] 67 #[salsa::invoke(crate::traits::impls_for_trait_query)]
68 fn impls_for_trait(&self, krate: CrateId, trait_: TraitId) -> Arc<[ImplId]>; 68 fn impls_for_trait(
69 &self,
70 krate: CrateId,
71 trait_: TraitId,
72 self_ty_fp: Option<TyFingerprint>,
73 ) -> Arc<[ImplId]>;
69 74
70 // Interned IDs for Chalk integration 75 // Interned IDs for Chalk integration
71 #[salsa::interned] 76 #[salsa::interned]
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 8cbce1168..927896d6f 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -21,7 +21,7 @@ impl Diagnostic for NoSuchField {
21 } 21 }
22 22
23 fn source(&self) -> InFile<SyntaxNodePtr> { 23 fn source(&self) -> InFile<SyntaxNodePtr> {
24 InFile { file_id: self.file, value: self.field.into() } 24 InFile { file_id: self.file, value: self.field.clone().into() }
25 } 25 }
26 26
27 fn as_any(&self) -> &(dyn Any + Send + 'static) { 27 fn as_any(&self) -> &(dyn Any + Send + 'static) {
@@ -45,7 +45,7 @@ impl Diagnostic for MissingFields {
45 buf 45 buf
46 } 46 }
47 fn source(&self) -> InFile<SyntaxNodePtr> { 47 fn source(&self) -> InFile<SyntaxNodePtr> {
48 InFile { file_id: self.file, value: self.field_list.into() } 48 InFile { file_id: self.file, value: self.field_list.clone().into() }
49 } 49 }
50 fn as_any(&self) -> &(dyn Any + Send + 'static) { 50 fn as_any(&self) -> &(dyn Any + Send + 'static) {
51 self 51 self
@@ -63,6 +63,29 @@ impl AstDiagnostic for MissingFields {
63} 63}
64 64
65#[derive(Debug)] 65#[derive(Debug)]
66pub struct MissingPatFields {
67 pub file: HirFileId,
68 pub field_list: AstPtr<ast::RecordFieldPatList>,
69 pub missed_fields: Vec<Name>,
70}
71
72impl Diagnostic for MissingPatFields {
73 fn message(&self) -> String {
74 let mut buf = String::from("Missing structure fields:\n");
75 for field in &self.missed_fields {
76 format_to!(buf, "- {}", field);
77 }
78 buf
79 }
80 fn source(&self) -> InFile<SyntaxNodePtr> {
81 InFile { file_id: self.file, value: self.field_list.clone().into() }
82 }
83 fn as_any(&self) -> &(dyn Any + Send + 'static) {
84 self
85 }
86}
87
88#[derive(Debug)]
66pub struct MissingMatchArms { 89pub struct MissingMatchArms {
67 pub file: HirFileId, 90 pub file: HirFileId,
68 pub match_expr: AstPtr<ast::Expr>, 91 pub match_expr: AstPtr<ast::Expr>,
@@ -74,7 +97,7 @@ impl Diagnostic for MissingMatchArms {
74 String::from("Missing match arm") 97 String::from("Missing match arm")
75 } 98 }
76 fn source(&self) -> InFile<SyntaxNodePtr> { 99 fn source(&self) -> InFile<SyntaxNodePtr> {
77 InFile { file_id: self.file, value: self.match_expr.into() } 100 InFile { file_id: self.file, value: self.match_expr.clone().into() }
78 } 101 }
79 fn as_any(&self) -> &(dyn Any + Send + 'static) { 102 fn as_any(&self) -> &(dyn Any + Send + 'static) {
80 self 103 self
@@ -92,7 +115,7 @@ impl Diagnostic for MissingOkInTailExpr {
92 "wrap return expression in Ok".to_string() 115 "wrap return expression in Ok".to_string()
93 } 116 }
94 fn source(&self) -> InFile<SyntaxNodePtr> { 117 fn source(&self) -> InFile<SyntaxNodePtr> {
95 InFile { file_id: self.file, value: self.expr.into() } 118 InFile { file_id: self.file, value: self.expr.clone().into() }
96 } 119 }
97 fn as_any(&self) -> &(dyn Any + Send + 'static) { 120 fn as_any(&self) -> &(dyn Any + Send + 'static) {
98 self 121 self
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 0e9313aa1..d03bbd5a7 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -247,19 +247,21 @@ impl HirDisplay for ApplicationTy {
247 } 247 }
248 } 248 }
249 TypeCtor::Closure { .. } => { 249 TypeCtor::Closure { .. } => {
250 let sig = self.parameters[0] 250 let sig = self.parameters[0].callable_sig(f.db);
251 .callable_sig(f.db) 251 if let Some(sig) = sig {
252 .expect("first closure parameter should contain signature"); 252 if sig.params().is_empty() {
253 if sig.params().is_empty() { 253 write!(f, "||")?;
254 write!(f, "||")?; 254 } else if f.omit_verbose_types() {
255 } else if f.omit_verbose_types() { 255 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?;
256 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?; 256 } else {
257 write!(f, "|")?;
258 f.write_joined(sig.params(), ", ")?;
259 write!(f, "|")?;
260 };
261 write!(f, " -> {}", sig.ret().display(f.db))?;
257 } else { 262 } else {
258 write!(f, "|")?; 263 write!(f, "{{closure}}")?;
259 f.write_joined(sig.params(), ", ")?; 264 }
260 write!(f, "|")?;
261 };
262 write!(f, " -> {}", sig.ret().display(f.db))?;
263 } 265 }
264 } 266 }
265 Ok(()) 267 Ok(())
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index e45e9ea14..69b527f74 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -9,7 +9,7 @@ use rustc_hash::FxHashSet;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr}, 12 diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields},
13 utils::variant_data, 13 utils::variant_data,
14 ApplicationTy, InferenceResult, Ty, TypeCtor, 14 ApplicationTy, InferenceResult, Ty, TypeCtor,
15 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, 15 _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness},
@@ -49,39 +49,95 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
49 if let Some((variant_def, missed_fields, true)) = 49 if let Some((variant_def, missed_fields, true)) =
50 record_literal_missing_fields(db, &self.infer, id, expr) 50 record_literal_missing_fields(db, &self.infer, id, expr)
51 { 51 {
52 // XXX: only look at source_map if we do have missing fields 52 self.create_record_literal_missing_fields_diagnostic(
53 let (_, source_map) = db.body_with_source_map(self.func.into()); 53 id,
54 54 db,
55 if let Ok(source_ptr) = source_map.expr_syntax(id) { 55 variant_def,
56 if let Some(expr) = source_ptr.value.left() { 56 missed_fields,
57 let root = source_ptr.file_syntax(db.upcast()); 57 );
58 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
59 if let Some(field_list) = record_lit.record_field_list() {
60 let variant_data = variant_data(db.upcast(), variant_def);
61 let missed_fields = missed_fields
62 .into_iter()
63 .map(|idx| variant_data.fields()[idx].name.clone())
64 .collect();
65 self.sink.push(MissingFields {
66 file: source_ptr.file_id,
67 field_list: AstPtr::new(&field_list),
68 missed_fields,
69 })
70 }
71 }
72 }
73 }
74 } 58 }
75 if let Expr::Match { expr, arms } = expr { 59 if let Expr::Match { expr, arms } = expr {
76 self.validate_match(id, *expr, arms, db, self.infer.clone()); 60 self.validate_match(id, *expr, arms, db, self.infer.clone());
77 } 61 }
78 } 62 }
63 for (id, pat) in body.pats.iter() {
64 if let Some((variant_def, missed_fields, true)) =
65 record_pattern_missing_fields(db, &self.infer, id, pat)
66 {
67 self.create_record_pattern_missing_fields_diagnostic(
68 id,
69 db,
70 variant_def,
71 missed_fields,
72 );
73 }
74 }
79 let body_expr = &body[body.body_expr]; 75 let body_expr = &body[body.body_expr];
80 if let Expr::Block { tail: Some(t), .. } = body_expr { 76 if let Expr::Block { tail: Some(t), .. } = body_expr {
81 self.validate_results_in_tail_expr(body.body_expr, *t, db); 77 self.validate_results_in_tail_expr(body.body_expr, *t, db);
82 } 78 }
83 } 79 }
84 80
81 fn create_record_literal_missing_fields_diagnostic(
82 &mut self,
83 id: ExprId,
84 db: &dyn HirDatabase,
85 variant_def: VariantId,
86 missed_fields: Vec<LocalStructFieldId>,
87 ) {
88 // XXX: only look at source_map if we do have missing fields
89 let (_, source_map) = db.body_with_source_map(self.func.into());
90
91 if let Ok(source_ptr) = source_map.expr_syntax(id) {
92 let root = source_ptr.file_syntax(db.upcast());
93 if let ast::Expr::RecordLit(record_lit) = &source_ptr.value.to_node(&root) {
94 if let Some(field_list) = record_lit.record_field_list() {
95 let variant_data = variant_data(db.upcast(), variant_def);
96 let missed_fields = missed_fields
97 .into_iter()
98 .map(|idx| variant_data.fields()[idx].name.clone())
99 .collect();
100 self.sink.push(MissingFields {
101 file: source_ptr.file_id,
102 field_list: AstPtr::new(&field_list),
103 missed_fields,
104 })
105 }
106 }
107 }
108 }
109
110 fn create_record_pattern_missing_fields_diagnostic(
111 &mut self,
112 id: PatId,
113 db: &dyn HirDatabase,
114 variant_def: VariantId,
115 missed_fields: Vec<LocalStructFieldId>,
116 ) {
117 // XXX: only look at source_map if we do have missing fields
118 let (_, source_map) = db.body_with_source_map(self.func.into());
119
120 if let Ok(source_ptr) = source_map.pat_syntax(id) {
121 if let Some(expr) = source_ptr.value.as_ref().left() {
122 let root = source_ptr.file_syntax(db.upcast());
123 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
124 if let Some(field_list) = record_pat.record_field_pat_list() {
125 let variant_data = variant_data(db.upcast(), variant_def);
126 let missed_fields = missed_fields
127 .into_iter()
128 .map(|idx| variant_data.fields()[idx].name.clone())
129 .collect();
130 self.sink.push(MissingPatFields {
131 file: source_ptr.file_id,
132 field_list: AstPtr::new(&field_list),
133 missed_fields,
134 })
135 }
136 }
137 }
138 }
139 }
140
85 fn validate_match( 141 fn validate_match(
86 &mut self, 142 &mut self,
87 id: ExprId, 143 id: ExprId,
@@ -147,18 +203,16 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
147 } 203 }
148 204
149 if let Ok(source_ptr) = source_map.expr_syntax(id) { 205 if let Ok(source_ptr) = source_map.expr_syntax(id) {
150 if let Some(expr) = source_ptr.value.left() { 206 let root = source_ptr.file_syntax(db.upcast());
151 let root = source_ptr.file_syntax(db.upcast()); 207 if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) {
152 if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) { 208 if let (Some(match_expr), Some(arms)) =
153 if let (Some(match_expr), Some(arms)) = 209 (match_expr.expr(), match_expr.match_arm_list())
154 (match_expr.expr(), match_expr.match_arm_list()) 210 {
155 { 211 self.sink.push(MissingMatchArms {
156 self.sink.push(MissingMatchArms { 212 file: source_ptr.file_id,
157 file: source_ptr.file_id, 213 match_expr: AstPtr::new(&match_expr),
158 match_expr: AstPtr::new(&match_expr), 214 arms: AstPtr::new(&arms),
159 arms: AstPtr::new(&arms), 215 })
160 })
161 }
162 } 216 }
163 } 217 }
164 } 218 }
@@ -189,9 +243,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
189 let (_, source_map) = db.body_with_source_map(self.func.into()); 243 let (_, source_map) = db.body_with_source_map(self.func.into());
190 244
191 if let Ok(source_ptr) = source_map.expr_syntax(id) { 245 if let Ok(source_ptr) = source_map.expr_syntax(id) {
192 if let Some(expr) = source_ptr.value.left() { 246 self.sink
193 self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); 247 .push(MissingOkInTailExpr { file: source_ptr.file_id, expr: source_ptr.value });
194 }
195 } 248 }
196 } 249 }
197 } 250 }
@@ -232,9 +285,9 @@ pub fn record_pattern_missing_fields(
232 infer: &InferenceResult, 285 infer: &InferenceResult,
233 id: PatId, 286 id: PatId,
234 pat: &Pat, 287 pat: &Pat,
235) -> Option<(VariantId, Vec<LocalStructFieldId>)> { 288) -> Option<(VariantId, Vec<LocalStructFieldId>, /*exhaustive*/ bool)> {
236 let fields = match pat { 289 let (fields, exhaustive) = match pat {
237 Pat::Record { path: _, args } => args, 290 Pat::Record { path: _, args, ellipsis } => (args, !ellipsis),
238 _ => return None, 291 _ => return None,
239 }; 292 };
240 293
@@ -254,5 +307,5 @@ pub fn record_pattern_missing_fields(
254 if missed_fields.is_empty() { 307 if missed_fields.is_empty() {
255 return None; 308 return None;
256 } 309 }
257 Some((variant_def, missed_fields)) 310 Some((variant_def, missed_fields, exhaustive))
258} 311}
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 69bbb4307..078476f76 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> {
158 Pat::TupleStruct { path: p, args: subpats } => { 158 Pat::TupleStruct { path: p, args: subpats } => {
159 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat) 159 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat)
160 } 160 }
161 Pat::Record { path: p, args: fields } => { 161 Pat::Record { path: p, args: fields, ellipsis: _ } => {
162 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 162 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
163 } 163 }
164 Pat::Path(path) => { 164 Pat::Path(path) => {
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 74a0bc7db..657284fd0 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -34,7 +34,7 @@ impl TyFingerprint {
34 /// Creates a TyFingerprint for looking up an impl. Only certain types can 34 /// Creates a TyFingerprint for looking up an impl. Only certain types can
35 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 35 /// have impls: if we have some `struct S`, we can have an `impl S`, but not
36 /// `impl &S`. Hence, this will return `None` for reference types and such. 36 /// `impl &S`. Hence, this will return `None` for reference types and such.
37 fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 37 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
38 match ty { 38 match ty {
39 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), 39 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
40 _ => None, 40 _ => None,
@@ -45,7 +45,7 @@ impl TyFingerprint {
45#[derive(Debug, PartialEq, Eq)] 45#[derive(Debug, PartialEq, Eq)]
46pub struct CrateImplDefs { 46pub struct CrateImplDefs {
47 impls: FxHashMap<TyFingerprint, Vec<ImplId>>, 47 impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
48 impls_by_trait: FxHashMap<TraitId, Vec<ImplId>>, 48 impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
49} 49}
50 50
51impl CrateImplDefs { 51impl CrateImplDefs {
@@ -59,7 +59,14 @@ impl CrateImplDefs {
59 for impl_id in module_data.scope.impls() { 59 for impl_id in module_data.scope.impls() {
60 match db.impl_trait(impl_id) { 60 match db.impl_trait(impl_id) {
61 Some(tr) => { 61 Some(tr) => {
62 res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id); 62 let self_ty = db.impl_self_ty(impl_id);
63 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
64 res.impls_by_trait
65 .entry(tr.value.trait_)
66 .or_default()
67 .entry(self_ty_fp)
68 .or_default()
69 .push(impl_id);
63 } 70 }
64 None => { 71 None => {
65 let self_ty = db.impl_self_ty(impl_id); 72 let self_ty = db.impl_self_ty(impl_id);
@@ -79,11 +86,39 @@ impl CrateImplDefs {
79 } 86 }
80 87
81 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { 88 pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
82 self.impls_by_trait.get(&tr).into_iter().flatten().copied() 89 self.impls_by_trait
90 .get(&tr)
91 .into_iter()
92 .flat_map(|m| m.values().flat_map(|v| v.iter().copied()))
93 }
94
95 pub fn lookup_impl_defs_for_trait_and_ty(
96 &self,
97 tr: TraitId,
98 fp: TyFingerprint,
99 ) -> impl Iterator<Item = ImplId> + '_ {
100 self.impls_by_trait
101 .get(&tr)
102 .and_then(|m| m.get(&Some(fp)))
103 .into_iter()
104 .flatten()
105 .copied()
106 .chain(
107 self.impls_by_trait
108 .get(&tr)
109 .and_then(|m| m.get(&None))
110 .into_iter()
111 .flatten()
112 .copied(),
113 )
83 } 114 }
84 115
85 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { 116 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
86 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() 117 self.impls
118 .values()
119 .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
120 .flatten()
121 .copied()
87 } 122 }
88} 123}
89 124
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 002cffba6..81fc0f63a 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -82,12 +82,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
82 82
83 for (expr, ty) in inference_result.type_of_expr.iter() { 83 for (expr, ty) in inference_result.type_of_expr.iter() {
84 let syntax_ptr = match body_source_map.expr_syntax(expr) { 84 let syntax_ptr = match body_source_map.expr_syntax(expr) {
85 Ok(sp) => { 85 Ok(sp) => sp.map(|ast| ast.syntax_node_ptr()),
86 sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()))
87 }
88 Err(SyntheticSyntax) => continue, 86 Err(SyntheticSyntax) => continue,
89 }; 87 };
90 types.push((syntax_ptr, ty)); 88 types.push((syntax_ptr.clone(), ty));
91 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { 89 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
92 mismatches.push((syntax_ptr, mismatch)); 90 mismatches.push((syntax_ptr, mismatch));
93 } 91 }
@@ -409,3 +407,43 @@ fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() {
409 407
410 assert_snapshot!(diagnostics, @r###""###); 408 assert_snapshot!(diagnostics, @r###""###);
411} 409}
410
411#[test]
412fn missing_record_pat_field_diagnostic() {
413 let diagnostics = TestDB::with_files(
414 r"
415 //- /lib.rs
416 struct S { foo: i32, bar: () }
417 fn baz(s: S) {
418 let S { foo: _ } = s;
419 }
420 ",
421 )
422 .diagnostics()
423 .0;
424
425 assert_snapshot!(diagnostics, @r###"
426 "{ foo: _ }": Missing structure fields:
427 - bar
428 "###
429 );
430}
431
432#[test]
433fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
434 let diagnostics = TestDB::with_files(
435 r"
436 //- /lib.rs
437 struct S { foo: i32, bar: () }
438 fn baz(s: S) -> i32 {
439 match s {
440 S { foo, .. } => foo,
441 }
442 }
443 ",
444 )
445 .diagnostics()
446 .0;
447
448 assert_snapshot!(diagnostics, @"");
449}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index ff4599b71..f2a9b1c40 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,10 +1,13 @@
1use std::fs;
2
1use insta::assert_snapshot; 3use insta::assert_snapshot;
2use ra_db::fixture::WithFixture; 4use ra_db::fixture::WithFixture;
3 5use test_utils::project_dir;
4use super::{infer, type_at, type_at_pos};
5 6
6use crate::test_db::TestDB; 7use crate::test_db::TestDB;
7 8
9use super::{infer, type_at, type_at_pos};
10
8#[test] 11#[test]
9fn cfg_impl_def() { 12fn cfg_impl_def() {
10 let (db, pos) = TestDB::with_position( 13 let (db, pos) = TestDB::with_position(
@@ -482,6 +485,30 @@ fn bar() -> u32 {0}
482} 485}
483 486
484#[test] 487#[test]
488#[ignore]
489fn include_accidentally_quadratic() {
490 let file = project_dir().join("crates/ra_syntax/test_data/accidentally_quadratic");
491 let big_file = fs::read_to_string(file).unwrap();
492 let big_file = vec![big_file; 10].join("\n");
493
494 let fixture = r#"
495//- /main.rs
496#[rustc_builtin_macro]
497macro_rules! include {() => {}}
498
499include!("foo.rs");
500
501fn main() {
502 RegisterBlock { }<|>;
503}
504 "#;
505 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file);
506
507 let (db, pos) = TestDB::with_position(&fixture);
508 assert_eq!("RegisterBlock", type_at_pos(&db, pos));
509}
510
511#[test]
485fn infer_builtin_macros_include_concat() { 512fn infer_builtin_macros_include_concat() {
486 let (db, pos) = TestDB::with_position( 513 let (db, pos) = TestDB::with_position(
487 r#" 514 r#"
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 5a1e12ce9..43d8d1e80 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -7,7 +7,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use crate::{db::HirDatabase, DebruijnIndex}; 10use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex};
11 11
12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
13 13
@@ -40,7 +40,12 @@ pub(crate) fn impls_for_trait_query(
40 db: &dyn HirDatabase, 40 db: &dyn HirDatabase,
41 krate: CrateId, 41 krate: CrateId,
42 trait_: TraitId, 42 trait_: TraitId,
43 self_ty_fp: Option<TyFingerprint>,
43) -> Arc<[ImplId]> { 44) -> Arc<[ImplId]> {
45 // FIXME: We could be a lot smarter here - because of the orphan rules and
46 // the fact that the trait and the self type need to be in the dependency
47 // tree of a crate somewhere for an impl to exist, we could skip looking in
48 // a lot of crates completely
44 let mut impls = FxHashSet::default(); 49 let mut impls = FxHashSet::default();
45 // We call the query recursively here. On the one hand, this means we can 50 // We call the query recursively here. On the one hand, this means we can
46 // reuse results from queries for different crates; on the other hand, this 51 // reuse results from queries for different crates; on the other hand, this
@@ -48,10 +53,13 @@ pub(crate) fn impls_for_trait_query(
48 // ones the user is editing), so this may actually be a waste of memory. I'm 53 // ones the user is editing), so this may actually be a waste of memory. I'm
49 // doing it like this mainly for simplicity for now. 54 // doing it like this mainly for simplicity for now.
50 for dep in &db.crate_graph()[krate].dependencies { 55 for dep in &db.crate_graph()[krate].dependencies {
51 impls.extend(db.impls_for_trait(dep.crate_id, trait_).iter()); 56 impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter());
52 } 57 }
53 let crate_impl_defs = db.impls_in_crate(krate); 58 let crate_impl_defs = db.impls_in_crate(krate);
54 impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)); 59 match self_ty_fp {
60 Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)),
61 None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)),
62 }
55 impls.into_iter().collect() 63 impls.into_iter().collect()
56} 64}
57 65
@@ -177,7 +185,7 @@ fn solve(
177 185
178 let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); 186 let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL);
179 187
180 let solution = solver.solve_limited(&context, goal, || { 188 let should_continue = || {
181 context.db.check_canceled(); 189 context.db.check_canceled();
182 let remaining = fuel.get(); 190 let remaining = fuel.get();
183 fuel.set(remaining - 1); 191 fuel.set(remaining - 1);
@@ -185,12 +193,21 @@ fn solve(
185 log::debug!("fuel exhausted"); 193 log::debug!("fuel exhausted");
186 } 194 }
187 remaining > 0 195 remaining > 0
188 }); 196 };
197 let mut solve = || solver.solve_limited(&context, goal, should_continue);
198 // don't set the TLS for Chalk unless Chalk debugging is active, to make
199 // extra sure we only use it for debugging
200 let solution =
201 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() };
189 202
190 log::debug!("solve({:?}) => {:?}", goal, solution); 203 log::debug!("solve({:?}) => {:?}", goal, solution);
191 solution 204 solution
192} 205}
193 206
207fn is_chalk_debug() -> bool {
208 std::env::var("CHALK_DEBUG").is_ok()
209}
210
194fn solution_from_chalk( 211fn solution_from_chalk(
195 db: &dyn HirDatabase, 212 db: &dyn HirDatabase,
196 solution: chalk_solve::Solution<Interner>, 213 solution: chalk_solve::Solution<Interner>,
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 1bc0f0713..e05fea843 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -16,10 +16,12 @@ use ra_db::{
16 16
17use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 17use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
18use crate::{ 18use crate::{
19 db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, 19 db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics,
20 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 20 ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
21}; 21};
22 22
23pub(super) mod tls;
24
23#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 25#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
24pub struct Interner; 26pub struct Interner;
25 27
@@ -33,90 +35,85 @@ impl chalk_ir::interner::Interner for Interner {
33 type Identifier = TypeAliasId; 35 type Identifier = TypeAliasId;
34 type DefId = InternId; 36 type DefId = InternId;
35 37
36 // FIXME: implement these
37 fn debug_struct_id( 38 fn debug_struct_id(
38 _type_kind_id: chalk_ir::StructId<Self>, 39 type_kind_id: StructId,
39 _fmt: &mut fmt::Formatter<'_>, 40 fmt: &mut fmt::Formatter<'_>,
40 ) -> Option<fmt::Result> { 41 ) -> Option<fmt::Result> {
41 None 42 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
42 } 43 }
43 44
44 fn debug_trait_id( 45 fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
45 _type_kind_id: chalk_ir::TraitId<Self>, 46 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
46 _fmt: &mut fmt::Formatter<'_>,
47 ) -> Option<fmt::Result> {
48 None
49 } 47 }
50 48
51 fn debug_assoc_type_id( 49 fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
52 _id: chalk_ir::AssocTypeId<Self>, 50 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
53 _fmt: &mut fmt::Formatter<'_>,
54 ) -> Option<fmt::Result> {
55 None
56 } 51 }
57 52
58 fn debug_alias( 53 fn debug_alias(
59 _projection: &chalk_ir::AliasTy<Self>, 54 alias: &chalk_ir::AliasTy<Interner>,
60 _fmt: &mut fmt::Formatter<'_>, 55 fmt: &mut fmt::Formatter<'_>,
61 ) -> Option<fmt::Result> { 56 ) -> Option<fmt::Result> {
62 None 57 tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt)))
63 } 58 }
64 59
65 fn debug_ty(_ty: &chalk_ir::Ty<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 60 fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
66 None 61 tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt)))
67 } 62 }
68 63
69 fn debug_lifetime( 64 fn debug_lifetime(
70 _lifetime: &chalk_ir::Lifetime<Self>, 65 lifetime: &chalk_ir::Lifetime<Interner>,
71 _fmt: &mut fmt::Formatter<'_>, 66 fmt: &mut fmt::Formatter<'_>,
72 ) -> Option<fmt::Result> { 67 ) -> Option<fmt::Result> {
73 None 68 tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt)))
74 } 69 }
75 70
76 fn debug_parameter( 71 fn debug_parameter(
77 _parameter: &Parameter<Self>, 72 parameter: &Parameter<Interner>,
78 _fmt: &mut fmt::Formatter<'_>, 73 fmt: &mut fmt::Formatter<'_>,
79 ) -> Option<fmt::Result> { 74 ) -> Option<fmt::Result> {
80 None 75 tls::with_current_program(|prog| Some(prog?.debug_parameter(parameter, fmt)))
81 } 76 }
82 77
83 fn debug_goal(_goal: &Goal<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 78 fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
84 None 79 tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt)))
85 } 80 }
86 81
87 fn debug_goals( 82 fn debug_goals(
88 _goals: &chalk_ir::Goals<Self>, 83 goals: &chalk_ir::Goals<Interner>,
89 _fmt: &mut fmt::Formatter<'_>, 84 fmt: &mut fmt::Formatter<'_>,
90 ) -> Option<fmt::Result> { 85 ) -> Option<fmt::Result> {
91 None 86 tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt)))
92 } 87 }
93 88
94 fn debug_program_clause_implication( 89 fn debug_program_clause_implication(
95 _pci: &chalk_ir::ProgramClauseImplication<Self>, 90 pci: &chalk_ir::ProgramClauseImplication<Interner>,
96 _fmt: &mut fmt::Formatter<'_>, 91 fmt: &mut fmt::Formatter<'_>,
97 ) -> Option<fmt::Result> { 92 ) -> Option<fmt::Result> {
98 None 93 tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt)))
99 } 94 }
100 95
101 fn debug_application_ty( 96 fn debug_application_ty(
102 _application_ty: &chalk_ir::ApplicationTy<Self>, 97 application_ty: &chalk_ir::ApplicationTy<Interner>,
103 _fmt: &mut fmt::Formatter<'_>, 98 fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> { 99 ) -> Option<fmt::Result> {
105 None 100 tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt)))
106 } 101 }
107 102
108 fn debug_substitution( 103 fn debug_substitution(
109 _substitution: &chalk_ir::Substitution<Self>, 104 substitution: &chalk_ir::Substitution<Interner>,
110 _fmt: &mut fmt::Formatter<'_>, 105 fmt: &mut fmt::Formatter<'_>,
111 ) -> Option<fmt::Result> { 106 ) -> Option<fmt::Result> {
112 None 107 tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt)))
113 } 108 }
114 109
115 fn debug_separator_trait_ref( 110 fn debug_separator_trait_ref(
116 _separator_trait_ref: &chalk_ir::SeparatorTraitRef<Self>, 111 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
117 _fmt: &mut fmt::Formatter<'_>, 112 fmt: &mut fmt::Formatter<'_>,
118 ) -> Option<fmt::Result> { 113 ) -> Option<fmt::Result> {
119 None 114 tls::with_current_program(|prog| {
115 Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt))
116 })
120 } 117 }
121 118
122 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 119 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
@@ -650,19 +647,22 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
650 debug!("impls_for_trait {:?}", trait_id); 647 debug!("impls_for_trait {:?}", trait_id);
651 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 648 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
652 649
650 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
651
652 let self_ty_fp = TyFingerprint::for_impl(&ty);
653
653 // Note: Since we're using impls_for_trait, only impls where the trait 654 // Note: Since we're using impls_for_trait, only impls where the trait
654 // can be resolved should ever reach Chalk. `impl_datum` relies on that 655 // can be resolved should ever reach Chalk. `impl_datum` relies on that
655 // and will panic if the trait can't be resolved. 656 // and will panic if the trait can't be resolved.
656 let mut result: Vec<_> = self 657 let mut result: Vec<_> = self
657 .db 658 .db
658 .impls_for_trait(self.krate, trait_) 659 .impls_for_trait(self.krate, trait_, self_ty_fp)
659 .iter() 660 .iter()
660 .copied() 661 .copied()
661 .map(Impl::ImplDef) 662 .map(Impl::ImplDef)
662 .map(|impl_| impl_.to_chalk(self.db)) 663 .map(|impl_| impl_.to_chalk(self.db))
663 .collect(); 664 .collect();
664 665
665 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
666 let arg: Option<Ty> = 666 let arg: Option<Ty> =
667 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone())); 667 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
668 668
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs
new file mode 100644
index 000000000..d9bbb54a5
--- /dev/null
+++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs
@@ -0,0 +1,231 @@
1//! Implementation of Chalk debug helper functions using TLS.
2use std::fmt;
3
4use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName};
5
6use super::{from_chalk, Interner};
7use crate::{db::HirDatabase, CallableDef, TypeCtor};
8use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
9
10pub use unsafe_tls::{set_current_program, with_current_program};
11
12pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a));
13
14impl DebugContext<'_> {
15 pub fn debug_struct_id(
16 &self,
17 id: super::StructId,
18 f: &mut fmt::Formatter<'_>,
19 ) -> Result<(), fmt::Error> {
20 let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id));
21 match type_ctor {
22 TypeCtor::Bool => write!(f, "bool")?,
23 TypeCtor::Char => write!(f, "char")?,
24 TypeCtor::Int(t) => write!(f, "{}", t)?,
25 TypeCtor::Float(t) => write!(f, "{}", t)?,
26 TypeCtor::Str => write!(f, "str")?,
27 TypeCtor::Slice => write!(f, "slice")?,
28 TypeCtor::Array => write!(f, "array")?,
29 TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?,
30 TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?,
31 TypeCtor::Never => write!(f, "!")?,
32 TypeCtor::Tuple { .. } => {
33 write!(f, "()")?;
34 }
35 TypeCtor::FnPtr { .. } => {
36 write!(f, "fn")?;
37 }
38 TypeCtor::FnDef(def) => {
39 let name = match def {
40 CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(),
41 CallableDef::StructId(s) => self.0.struct_data(s).name.clone(),
42 CallableDef::EnumVariantId(e) => {
43 let enum_data = self.0.enum_data(e.parent);
44 enum_data.variants[e.local_id].name.clone()
45 }
46 };
47 match def {
48 CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
49 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
50 write!(f, "{{ctor {}}}", name)?
51 }
52 }
53 }
54 TypeCtor::Adt(def_id) => {
55 let name = match def_id {
56 AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
57 AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
58 AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
59 };
60 write!(f, "{}", name)?;
61 }
62 TypeCtor::AssociatedType(type_alias) => {
63 let trait_ = match type_alias.lookup(self.0.upcast()).container {
64 AssocContainerId::TraitId(it) => it,
65 _ => panic!("not an associated type"),
66 };
67 let trait_name = self.0.trait_data(trait_).name.clone();
68 let name = self.0.type_alias_data(type_alias).name.clone();
69 write!(f, "{}::{}", trait_name, name)?;
70 }
71 TypeCtor::Closure { def, expr } => {
72 write!(f, "{{closure {:?} in {:?}}}", expr.into_raw(), def)?;
73 }
74 }
75 Ok(())
76 }
77
78 pub fn debug_trait_id(
79 &self,
80 id: super::TraitId,
81 fmt: &mut fmt::Formatter<'_>,
82 ) -> Result<(), fmt::Error> {
83 let trait_: hir_def::TraitId = from_chalk(self.0, id);
84 let trait_data = self.0.trait_data(trait_);
85 write!(fmt, "{}", trait_data.name)
86 }
87
88 pub fn debug_assoc_type_id(
89 &self,
90 id: super::AssocTypeId,
91 fmt: &mut fmt::Formatter<'_>,
92 ) -> Result<(), fmt::Error> {
93 let type_alias: TypeAliasId = from_chalk(self.0, id);
94 let type_alias_data = self.0.type_alias_data(type_alias);
95 let trait_ = match type_alias.lookup(self.0.upcast()).container {
96 AssocContainerId::TraitId(t) => t,
97 _ => panic!("associated type not in trait"),
98 };
99 let trait_data = self.0.trait_data(trait_);
100 write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
101 }
102
103 pub fn debug_alias(
104 &self,
105 alias: &AliasTy<Interner>,
106 fmt: &mut fmt::Formatter<'_>,
107 ) -> Result<(), fmt::Error> {
108 let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id);
109 let type_alias_data = self.0.type_alias_data(type_alias);
110 let trait_ = match type_alias.lookup(self.0.upcast()).container {
111 AssocContainerId::TraitId(t) => t,
112 _ => panic!("associated type not in trait"),
113 };
114 let trait_data = self.0.trait_data(trait_);
115 let params = alias.substitution.parameters(&Interner);
116 write!(
117 fmt,
118 "<{:?} as {}<{:?}>>::{}",
119 &params[0],
120 trait_data.name,
121 &params[1..],
122 type_alias_data.name
123 )
124 }
125
126 pub fn debug_ty(
127 &self,
128 ty: &chalk_ir::Ty<Interner>,
129 fmt: &mut fmt::Formatter<'_>,
130 ) -> Result<(), fmt::Error> {
131 write!(fmt, "{:?}", ty.data(&Interner))
132 }
133
134 pub fn debug_lifetime(
135 &self,
136 lifetime: &Lifetime<Interner>,
137 fmt: &mut fmt::Formatter<'_>,
138 ) -> Result<(), fmt::Error> {
139 write!(fmt, "{:?}", lifetime.data(&Interner))
140 }
141
142 pub fn debug_parameter(
143 &self,
144 parameter: &Parameter<Interner>,
145 fmt: &mut fmt::Formatter<'_>,
146 ) -> Result<(), fmt::Error> {
147 write!(fmt, "{:?}", parameter.data(&Interner).inner_debug())
148 }
149
150 pub fn debug_goal(
151 &self,
152 goal: &Goal<Interner>,
153 fmt: &mut fmt::Formatter<'_>,
154 ) -> Result<(), fmt::Error> {
155 let goal_data = goal.data(&Interner);
156 write!(fmt, "{:?}", goal_data)
157 }
158
159 pub fn debug_goals(
160 &self,
161 goals: &Goals<Interner>,
162 fmt: &mut fmt::Formatter<'_>,
163 ) -> Result<(), fmt::Error> {
164 write!(fmt, "{:?}", goals.debug(&Interner))
165 }
166
167 pub fn debug_program_clause_implication(
168 &self,
169 pci: &ProgramClauseImplication<Interner>,
170 fmt: &mut fmt::Formatter<'_>,
171 ) -> Result<(), fmt::Error> {
172 write!(fmt, "{:?}", pci.debug(&Interner))
173 }
174
175 pub fn debug_application_ty(
176 &self,
177 application_ty: &chalk_ir::ApplicationTy<Interner>,
178 fmt: &mut fmt::Formatter<'_>,
179 ) -> Result<(), fmt::Error> {
180 write!(fmt, "{:?}", application_ty.debug(&Interner))
181 }
182
183 pub fn debug_substitution(
184 &self,
185 substitution: &chalk_ir::Substitution<Interner>,
186 fmt: &mut fmt::Formatter<'_>,
187 ) -> Result<(), fmt::Error> {
188 write!(fmt, "{:?}", substitution.debug(&Interner))
189 }
190
191 pub fn debug_separator_trait_ref(
192 &self,
193 separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
194 fmt: &mut fmt::Formatter<'_>,
195 ) -> Result<(), fmt::Error> {
196 write!(fmt, "{:?}", separator_trait_ref.debug(&Interner))
197 }
198}
199
200mod unsafe_tls {
201 use super::DebugContext;
202 use crate::db::HirDatabase;
203 use scoped_tls::scoped_thread_local;
204
205 scoped_thread_local!(static PROGRAM: DebugContext);
206
207 pub fn with_current_program<R>(
208 op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
209 ) -> R {
210 if PROGRAM.is_set() {
211 PROGRAM.with(|prog| op(Some(prog)))
212 } else {
213 op(None)
214 }
215 }
216
217 pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
218 where
219 OP: FnOnce() -> R,
220 {
221 let ctx = DebugContext(p);
222 // we're transmuting the lifetime in the DebugContext to static. This is
223 // fine because we only keep the reference for the lifetime of this
224 // function, *and* the only way to access the context is through
225 // `with_current_program`, which hides the lifetime through the `for`
226 // type.
227 let static_p: &DebugContext<'static> =
228 unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) };
229 PROGRAM.set(static_p, || op())
230 }
231}
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index ded1ff3bc..fab02945c 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -35,7 +35,7 @@ use hir::{self, Docs, HasSource};
35use ra_assists::utils::get_missing_impl_items; 35use ra_assists::utils::get_missing_impl_items;
36use ra_syntax::{ 36use ra_syntax::{
37 ast::{self, edit, ImplDef}, 37 ast::{self, edit, ImplDef},
38 AstNode, SyntaxKind, SyntaxNode, TextRange, 38 AstNode, SyntaxKind, SyntaxNode, TextRange, T,
39}; 39};
40use ra_text_edit::TextEdit; 40use ra_text_edit::TextEdit;
41 41
@@ -204,7 +204,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
204 let end = const_ 204 let end = const_
205 .syntax() 205 .syntax()
206 .children_with_tokens() 206 .children_with_tokens()
207 .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ) 207 .find(|s| s.kind() == T![;] || s.kind() == T![=])
208 .map_or(const_end, |f| f.text_range().start()); 208 .map_or(const_end, |f| f.text_range().start());
209 209
210 let len = end - start; 210 let len = end - start;
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs
index efde9bf73..0b0da6ee4 100644
--- a/crates/ra_ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs
@@ -3,7 +3,7 @@
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
5pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
6 if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) { 6 if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const && !ctx.record_lit_syntax.is_some()) {
7 return; 7 return;
8 } 8 }
9 9
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 6637afaf7..14a4a14d7 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -227,7 +227,7 @@ impl<'a> CompletionContext<'a> {
227 self.name_ref_syntax = 227 self.name_ref_syntax =
228 find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); 228 find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
229 let name_range = name_ref.syntax().text_range(); 229 let name_range = name_ref.syntax().text_range();
230 if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { 230 if ast::RecordField::for_field_name(&name_ref).is_some() {
231 self.record_lit_syntax = 231 self.record_lit_syntax =
232 self.sema.find_node_at_offset_with_macros(&original_file, offset); 232 self.sema.find_node_at_offset_with_macros(&original_file, offset);
233 } 233 }
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index da9f55a69..45b9f7802 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -235,7 +235,10 @@ fn should_show_param_hint(
235 param_name: &str, 235 param_name: &str,
236 argument: &ast::Expr, 236 argument: &ast::Expr,
237) -> bool { 237) -> bool {
238 if param_name.is_empty() || is_argument_similar_to_param(argument, param_name) { 238 if param_name.is_empty()
239 || is_argument_similar_to_param(argument, param_name)
240 || Some(param_name) == fn_signature.name.as_ref().map(String::as_str)
241 {
239 return false; 242 return false;
240 } 243 }
241 244
@@ -247,10 +250,7 @@ fn should_show_param_hint(
247 250
248 // avoid displaying hints for common functions like map, filter, etc. 251 // avoid displaying hints for common functions like map, filter, etc.
249 // or other obvious words used in std 252 // or other obvious words used in std
250 if parameters_len == 1 && is_obvious_param(param_name) { 253 parameters_len != 1 || !is_obvious_param(param_name)
251 return false;
252 }
253 true
254} 254}
255 255
256fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool { 256fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool {
@@ -1086,6 +1086,8 @@ impl Test {
1086 } 1086 }
1087 1087
1088 fn no_hints_expected(&self, _: i32, test_var: i32) {} 1088 fn no_hints_expected(&self, _: i32, test_var: i32) {}
1089
1090 fn frob(&self, frob: bool) {}
1089} 1091}
1090 1092
1091struct Param {} 1093struct Param {}
@@ -1093,6 +1095,8 @@ struct Param {}
1093fn different_order(param: &Param) {} 1095fn different_order(param: &Param) {}
1094fn different_order_mut(param: &mut Param) {} 1096fn different_order_mut(param: &mut Param) {}
1095 1097
1098fn twiddle(twiddle: bool) {}
1099
1096fn main() { 1100fn main() {
1097 let container: TestVarContainer = TestVarContainer { test_var: 42 }; 1101 let container: TestVarContainer = TestVarContainer { test_var: 42 };
1098 let test: Test = Test {}; 1102 let test: Test = Test {};
@@ -1105,6 +1109,9 @@ fn main() {
1105 let test_var: i32 = 55; 1109 let test_var: i32 = 55;
1106 test_processed.no_hints_expected(22, test_var); 1110 test_processed.no_hints_expected(22, test_var);
1107 test_processed.no_hints_expected(33, container.test_var); 1111 test_processed.no_hints_expected(33, container.test_var);
1112 test_processed.frob(false);
1113
1114 twiddle(true);
1108 1115
1109 let param_begin: Param = Param {}; 1116 let param_begin: Param = Param {};
1110 different_order(&param_begin); 1117 different_order(&param_begin);
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs
index f58e436d1..5842ae2e8 100644
--- a/crates/ra_ide/src/syntax_tree.rs
+++ b/crates/ra_ide/src/syntax_tree.rs
@@ -165,7 +165,7 @@ SOURCE_FILE@[0; 60)
165 PATH_SEGMENT@[16; 22) 165 PATH_SEGMENT@[16; 22)
166 NAME_REF@[16; 22) 166 NAME_REF@[16; 22)
167 IDENT@[16; 22) "assert" 167 IDENT@[16; 22) "assert"
168 EXCL@[22; 23) "!" 168 BANG@[22; 23) "!"
169 TOKEN_TREE@[23; 57) 169 TOKEN_TREE@[23; 57)
170 L_PAREN@[23; 24) "(" 170 L_PAREN@[23; 24) "("
171 STRING@[24; 52) "\"\n fn foo() {\n ..." 171 STRING@[24; 52) "\"\n fn foo() {\n ..."
@@ -173,7 +173,7 @@ SOURCE_FILE@[0; 60)
173 WHITESPACE@[53; 54) " " 173 WHITESPACE@[53; 54) " "
174 STRING@[54; 56) "\"\"" 174 STRING@[54; 56) "\"\""
175 R_PAREN@[56; 57) ")" 175 R_PAREN@[56; 57) ")"
176 SEMI@[57; 58) ";" 176 SEMICOLON@[57; 58) ";"
177 WHITESPACE@[58; 59) "\n" 177 WHITESPACE@[58; 59) "\n"
178 R_CURLY@[59; 60) "}" 178 R_CURLY@[59; 60) "}"
179"# 179"#
@@ -226,7 +226,7 @@ EXPR_STMT@[16; 58)
226 PATH_SEGMENT@[16; 22) 226 PATH_SEGMENT@[16; 22)
227 NAME_REF@[16; 22) 227 NAME_REF@[16; 22)
228 IDENT@[16; 22) "assert" 228 IDENT@[16; 22) "assert"
229 EXCL@[22; 23) "!" 229 BANG@[22; 23) "!"
230 TOKEN_TREE@[23; 57) 230 TOKEN_TREE@[23; 57)
231 L_PAREN@[23; 24) "(" 231 L_PAREN@[23; 24) "("
232 STRING@[24; 52) "\"\n fn foo() {\n ..." 232 STRING@[24; 52) "\"\n fn foo() {\n ..."
@@ -234,7 +234,7 @@ EXPR_STMT@[16; 58)
234 WHITESPACE@[53; 54) " " 234 WHITESPACE@[53; 54) " "
235 STRING@[54; 56) "\"\"" 235 STRING@[54; 56) "\"\""
236 R_PAREN@[56; 57) ")" 236 R_PAREN@[56; 57) ")"
237 SEMI@[57; 58) ";" 237 SEMICOLON@[57; 58) ";"
238"# 238"#
239 .trim() 239 .trim()
240 ); 240 );
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 71d2bcb04..f55cd3bf5 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -63,7 +63,7 @@ fn on_char_typed_inner(
63fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { 63fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> {
64 assert_eq!(file.syntax().text().char_at(offset), Some('=')); 64 assert_eq!(file.syntax().text().char_at(offset), Some('='));
65 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; 65 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
66 if let_stmt.semi_token().is_some() { 66 if let_stmt.semicolon_token().is_some() {
67 return None; 67 return None;
68 } 68 }
69 if let Some(expr) = let_stmt.initializer() { 69 if let Some(expr) = let_stmt.initializer() {
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index e9934844e..49a8c74fb 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -216,7 +216,7 @@ pub fn classify_name_ref(
216 } 216 }
217 } 217 }
218 218
219 if let Some(record_field) = ast::RecordField::cast(parent.clone()) { 219 if let Some(record_field) = ast::RecordField::for_field_name(name_ref) {
220 tested_by!(goto_def_for_record_fields; force); 220 tested_by!(goto_def_for_record_fields; force);
221 tested_by!(goto_def_for_field_init_shorthand; force); 221 tested_by!(goto_def_for_field_init_shorthand; force);
222 if let Some((field, local)) = sema.resolve_record_field(&record_field) { 222 if let Some((field, local)) = sema.resolve_record_field(&record_field) {
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 8e8ae2b29..9fb5cb058 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -137,21 +137,23 @@ impl TokenMap {
137 token_id: tt::TokenId, 137 token_id: tt::TokenId,
138 open_relative_range: TextRange, 138 open_relative_range: TextRange,
139 close_relative_range: TextRange, 139 close_relative_range: TextRange,
140 ) { 140 ) -> usize {
141 let res = self.entries.len();
141 self.entries 142 self.entries
142 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); 143 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range)));
144 res
143 } 145 }
144 146
145 fn update_close_delim(&mut self, token_id: tt::TokenId, close_relative_range: TextRange) { 147 fn update_close_delim(&mut self, idx: usize, close_relative_range: TextRange) {
146 if let Some(entry) = self.entries.iter_mut().find(|(tid, _)| *tid == token_id) { 148 let (_, token_text_range) = &mut self.entries[idx];
147 if let TokenTextRange::Delimiter(dim, _) = entry.1 { 149 if let TokenTextRange::Delimiter(dim, _) = token_text_range {
148 entry.1 = TokenTextRange::Delimiter(dim, close_relative_range); 150 *token_text_range = TokenTextRange::Delimiter(*dim, close_relative_range);
149 }
150 } 151 }
151 } 152 }
152 153
153 fn remove_delim(&mut self, token_id: tt::TokenId) { 154 fn remove_delim(&mut self, idx: usize) {
154 self.entries.retain(|(tid, _)| *tid != token_id); 155 // FIXME: This could be accidently quadratic
156 self.entries.remove(idx);
155 } 157 }
156} 158}
157 159
@@ -238,24 +240,24 @@ impl TokenIdAlloc {
238 token_id 240 token_id
239 } 241 }
240 242
241 fn open_delim(&mut self, open_abs_range: TextRange) -> tt::TokenId { 243 fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
242 let token_id = tt::TokenId(self.next_id); 244 let token_id = tt::TokenId(self.next_id);
243 self.next_id += 1; 245 self.next_id += 1;
244 self.map.insert_delim( 246 let idx = self.map.insert_delim(
245 token_id, 247 token_id,
246 open_abs_range - self.global_offset, 248 open_abs_range - self.global_offset,
247 open_abs_range - self.global_offset, 249 open_abs_range - self.global_offset,
248 ); 250 );
249 token_id 251 (token_id, idx)
250 } 252 }
251 253
252 fn close_delim(&mut self, id: tt::TokenId, close_abs_range: Option<TextRange>) { 254 fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) {
253 match close_abs_range { 255 match close_abs_range {
254 None => { 256 None => {
255 self.map.remove_delim(id); 257 self.map.remove_delim(idx);
256 } 258 }
257 Some(close) => { 259 Some(close) => {
258 self.map.update_close_delim(id, close - self.global_offset); 260 self.map.update_close_delim(idx, close - self.global_offset);
259 } 261 }
260 } 262 }
261 } 263 }
@@ -322,7 +324,7 @@ trait TokenConvertor {
322 324
323 if let Some((kind, closed)) = delim { 325 if let Some((kind, closed)) = delim {
324 let mut subtree = tt::Subtree::default(); 326 let mut subtree = tt::Subtree::default();
325 let id = self.id_alloc().open_delim(range); 327 let (id, idx) = self.id_alloc().open_delim(range);
326 subtree.delimiter = Some(tt::Delimiter { kind, id }); 328 subtree.delimiter = Some(tt::Delimiter { kind, id });
327 329
328 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { 330 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) {
@@ -331,7 +333,7 @@ trait TokenConvertor {
331 let last_range = match self.bump() { 333 let last_range = match self.bump() {
332 None => { 334 None => {
333 // For error resilience, we insert an char punct for the opening delim here 335 // For error resilience, we insert an char punct for the opening delim here
334 self.id_alloc().close_delim(id, None); 336 self.id_alloc().close_delim(idx, None);
335 let leaf: tt::Leaf = tt::Punct { 337 let leaf: tt::Leaf = tt::Punct {
336 id: self.id_alloc().alloc(range), 338 id: self.id_alloc().alloc(range),
337 char: token.to_char().unwrap(), 339 char: token.to_char().unwrap(),
@@ -344,7 +346,7 @@ trait TokenConvertor {
344 } 346 }
345 Some(it) => it.1, 347 Some(it) => it.1,
346 }; 348 };
347 self.id_alloc().close_delim(id, Some(last_range)); 349 self.id_alloc().close_delim(idx, Some(last_range));
348 subtree.into() 350 subtree.into()
349 } else { 351 } else {
350 let spacing = match self.peek() { 352 let spacing = match self.peek() {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 1ef6f6eed..5d1274d21 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -252,7 +252,7 @@ fn test_expr_order() {
252 STAR@[11; 12) "*" 252 STAR@[11; 12) "*"
253 LITERAL@[12; 13) 253 LITERAL@[12; 13)
254 INT_NUMBER@[12; 13) "2" 254 INT_NUMBER@[12; 13) "2"
255 SEMI@[13; 14) ";" 255 SEMICOLON@[13; 14) ";"
256 R_CURLY@[14; 15) "}""#, 256 R_CURLY@[14; 15) "}""#,
257 ); 257 );
258} 258}
@@ -605,7 +605,7 @@ fn test_tt_to_stmts() {
605 EQ@[4; 5) "=" 605 EQ@[4; 5) "="
606 LITERAL@[5; 6) 606 LITERAL@[5; 6)
607 INT_NUMBER@[5; 6) "0" 607 INT_NUMBER@[5; 6) "0"
608 SEMI@[6; 7) ";" 608 SEMICOLON@[6; 7) ";"
609 EXPR_STMT@[7; 14) 609 EXPR_STMT@[7; 14)
610 BIN_EXPR@[7; 13) 610 BIN_EXPR@[7; 13)
611 PATH_EXPR@[7; 8) 611 PATH_EXPR@[7; 8)
@@ -620,7 +620,7 @@ fn test_tt_to_stmts() {
620 PLUS@[11; 12) "+" 620 PLUS@[11; 12) "+"
621 LITERAL@[12; 13) 621 LITERAL@[12; 13)
622 INT_NUMBER@[12; 13) "1" 622 INT_NUMBER@[12; 13) "1"
623 SEMI@[13; 14) ";" 623 SEMICOLON@[13; 14) ";"
624 EXPR_STMT@[14; 15) 624 EXPR_STMT@[14; 15)
625 PATH_EXPR@[14; 15) 625 PATH_EXPR@[14; 15)
626 PATH@[14; 15) 626 PATH@[14; 15)
@@ -953,7 +953,7 @@ fn test_tt_composite2() {
953 PATH_SEGMENT@[0; 3) 953 PATH_SEGMENT@[0; 3)
954 NAME_REF@[0; 3) 954 NAME_REF@[0; 3)
955 IDENT@[0; 3) "abs" 955 IDENT@[0; 3) "abs"
956 EXCL@[3; 4) "!" 956 BANG@[3; 4) "!"
957 TOKEN_TREE@[4; 10) 957 TOKEN_TREE@[4; 10)
958 L_PAREN@[4; 5) "(" 958 L_PAREN@[4; 5) "("
959 EQ@[5; 6) "=" 959 EQ@[5; 6) "="
@@ -1073,14 +1073,14 @@ fn test_vec() {
1073 PATH_SEGMENT@[9; 12) 1073 PATH_SEGMENT@[9; 12)
1074 NAME_REF@[9; 12) 1074 NAME_REF@[9; 12)
1075 IDENT@[9; 12) "Vec" 1075 IDENT@[9; 12) "Vec"
1076 COLONCOLON@[12; 14) "::" 1076 COLON2@[12; 14) "::"
1077 PATH_SEGMENT@[14; 17) 1077 PATH_SEGMENT@[14; 17)
1078 NAME_REF@[14; 17) 1078 NAME_REF@[14; 17)
1079 IDENT@[14; 17) "new" 1079 IDENT@[14; 17) "new"
1080 ARG_LIST@[17; 19) 1080 ARG_LIST@[17; 19)
1081 L_PAREN@[17; 18) "(" 1081 L_PAREN@[17; 18) "("
1082 R_PAREN@[18; 19) ")" 1082 R_PAREN@[18; 19) ")"
1083 SEMI@[19; 20) ";" 1083 SEMICOLON@[19; 20) ";"
1084 EXPR_STMT@[20; 33) 1084 EXPR_STMT@[20; 33)
1085 METHOD_CALL_EXPR@[20; 32) 1085 METHOD_CALL_EXPR@[20; 32)
1086 PATH_EXPR@[20; 21) 1086 PATH_EXPR@[20; 21)
@@ -1096,7 +1096,7 @@ fn test_vec() {
1096 LITERAL@[27; 31) 1096 LITERAL@[27; 31)
1097 INT_NUMBER@[27; 31) "1u32" 1097 INT_NUMBER@[27; 31) "1u32"
1098 R_PAREN@[31; 32) ")" 1098