Skip to content

Commit 5be3b85

Browse files
committed
feat: hint about inaccessible private declaration on dot notation failure
1 parent 803ec8f commit 5be3b85

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

src/Lean/Elab/App.lean

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,8 +1261,11 @@ inductive LValResolution where
12611261
The `baseName` is the base name of the type to search for in the parameter list. -/
12621262
| localRec (baseName : Name) (fvar : Expr)
12631263

1264+
private def mkLValError (e : Expr) (eType : Expr) (msg : MessageData) : MessageData :=
1265+
m!"{msg}{indentExpr e}\nhas type{indentExpr eType}"
1266+
12641267
private def throwLValErrorAt (ref : Syntax) (e : Expr) (eType : Expr) (msg : MessageData) : TermElabM α :=
1265-
throwErrorAt ref "{msg}{indentExpr e}\nhas type{indentExpr eType}"
1268+
throwErrorAt ref (mkLValError e eType msg)
12661269

12671270
private def throwLValError (e : Expr) (eType : Expr) (msg : MessageData) : TermElabM α := do
12681271
throwLValErrorAt (← getRef) e eType msg
@@ -1329,9 +1332,13 @@ where
13291332
| some (_, p2) => prodArity p2 + 1
13301333

13311334
private def resolveLValAux (e : Expr) (eType : Expr) (lval : LVal) : TermElabM LValResolution := do
1332-
let throwInvalidFieldAt {α : Type} (ref : Syntax) (fieldName : String) (fullName : Name) : TermElabM α := do
1333-
throwLValErrorAt ref e eType <| ← mkUnknownIdentifierMessage (declHint := fullName)
1334-
m!"Invalid field `{fieldName}`: The environment does not contain `{fullName}`"
1335+
let throwInvalidFieldAt {α : Type} (ref : Syntax) (fieldName : String) (fullName : Name)
1336+
(declHint := Name.anonymous) : TermElabM α := do
1337+
throwErrorAt ref (←
1338+
-- ordering: put decl hint, if any, last
1339+
mkUnknownIdentifierMessage (declHint := declHint)
1340+
(mkLValError e eType
1341+
m!"Invalid field `{fieldName}`: The environment does not contain `{fullName}`"))
13351342
if eType.isForall then
13361343
match lval with
13371344
| LVal.fieldName _ fieldName suffix? fullRef =>
@@ -1397,6 +1404,9 @@ private def resolveLValAux (e : Expr) (eType : Expr) (lval : LVal) : TermElabM L
13971404
if let some (baseStructName, fullName) ← findMethod? structName (.mkSimple fieldName) then
13981405
return LValResolution.const baseStructName structName fullName
13991406
throwInvalidFieldAt fullRef fieldName fullName
1407+
-- Suggest a potential unreachable private name as hint. This does not cover structure
1408+
-- inheritance, nor `import all`.
1409+
(declHint := (mkPrivateName env structName).mkStr fieldName)
14001410
| none, LVal.fieldName _ _ (some suffix) fullRef =>
14011411
-- This may be a function constant whose implicit arguments have already been filled in:
14021412
let c := e.getAppFn

src/Lean/Elab/Term/TermElabM.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ where
19741974
let env ← getEnv
19751975
-- check for scope errors before trying auto implicits
19761976
if env.isExporting then
1977-
if let [(npriv, _)] ← withEnv (env.setExporting false) <| resolveGlobalName n then
1977+
if let [(npriv, _)] ← withoutExporting <| resolveGlobalName n then
19781978
throwUnknownIdentifierAt (declHint := npriv) stx m!"Unknown identifier `{.ofConstName n}`"
19791979
if (← read).autoBoundImplicit &&
19801980
!(← read).autoBoundImplicitForbidden n &&

tests/pkg/module/Module/Basic.lean

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,3 +469,20 @@ info: @[expose] meta def msecexp : Nat :=
469469
#print msecexp
470470
471471
attribute [simp] f_struct
472+
473+
/-! Error message on private dot notation access. -/
474+
475+
public structure S
476+
477+
def S.s := 1
478+
479+
/--
480+
error: Invalid field `s`: The environment does not contain `S.s`
481+
s
482+
has type
483+
S
484+
485+
Note: A private declaration `S.s` (from the current module) exists but would need to be public to access here.
486+
-/
487+
#guard_msgs in
488+
@[expose] public def useS (s : S) := s.s

0 commit comments

Comments
 (0)